From 1e2dfc207612eca49a4ea1b900abc9f2ae2b6b04 Mon Sep 17 00:00:00 2001 From: Sergey Kolupaev Date: Wed, 4 Sep 2024 19:39:06 -0700 Subject: [PATCH 1/2] Make LoadV2 methos public --- KeeperSdk/KeeperSdk.csproj | 2 +- KeeperSdk/vault/VaultExtensions.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/KeeperSdk/KeeperSdk.csproj b/KeeperSdk/KeeperSdk.csproj index a424807..77e5baa 100644 --- a/KeeperSdk/KeeperSdk.csproj +++ b/KeeperSdk/KeeperSdk.csproj @@ -3,7 +3,7 @@ netstandard2.0;net452 7.1 - 1.0.5 + 1.0.6-beta01 Keeper Security Inc. .NET Keeper Sdk keeper password manager diff --git a/KeeperSdk/vault/VaultExtensions.cs b/KeeperSdk/vault/VaultExtensions.cs index a03b4c1..8544436 100644 --- a/KeeperSdk/vault/VaultExtensions.cs +++ b/KeeperSdk/vault/VaultExtensions.cs @@ -419,7 +419,7 @@ internal static RecordTypeData ExtractRecordV3Data(this TypedRecord typedRecord) private static readonly DataContractJsonSerializer ExtraSerializer = new DataContractJsonSerializer(typeof(RecordExtra), JsonUtils.JsonSettings); - internal static KeeperRecord Load(this IStorageRecord r, byte[] key) + public static KeeperRecord Load(this IStorageRecord r, byte[] key) { KeeperRecord record = null; switch (r.Version) @@ -443,7 +443,7 @@ record = r.LoadV5(key); return record; } - internal static PasswordRecord LoadV2(this IStorageRecord r, byte[] key) + public static PasswordRecord LoadV2(this IStorageRecord r, byte[] key) { var record = new PasswordRecord() { From 5ec727b3b566a61f9a47a9397cab4a16f7620ca1 Mon Sep 17 00:00:00 2001 From: Sergey Kolupaev Date: Wed, 16 Oct 2024 13:06:32 -0700 Subject: [PATCH 2/2] PowerCommander: Display enterprise role --- Commander/Commander.csproj | 1 - Commander/Properties/AssemblyInfo.cs | 6 +- Commander/enterprise/EnterpriseCommands.cs | 27 ++- Commander/enterprise/RoleDataManagement.cs | 120 ----------- KeeperSdk/KeeperSdk.csproj | 6 +- KeeperSdk/enterprise/EnterpriseTypes.cs | 6 +- KeeperSdk/enterprise/RoleData.cs | 84 +++++++- KeeperSdk/enterprise/RoleManagement.cs | 177 ++++++++++++++++ PowerCommander/Enterprise.format.ps1xml | 138 ++++++++++++- PowerCommander/Enterprise.ps1 | 226 ++++++++++++++++++++- PowerCommander/Enterprise.types.ps1xml | 60 +++++- PowerCommander/ManagedCompany.ps1 | 16 -- PowerCommander/PowerCommander.psd1 | 16 +- PowerCommander/PowerCommander.psm1 | 12 +- PowerCommander/README.md | 3 + 15 files changed, 717 insertions(+), 181 deletions(-) delete mode 100644 Commander/enterprise/RoleDataManagement.cs create mode 100644 KeeperSdk/enterprise/RoleManagement.cs diff --git a/Commander/Commander.csproj b/Commander/Commander.csproj index 094d4e9..dae22f0 100644 --- a/Commander/Commander.csproj +++ b/Commander/Commander.csproj @@ -92,7 +92,6 @@ - diff --git a/Commander/Properties/AssemblyInfo.cs b/Commander/Properties/AssemblyInfo.cs index 9274666..98a8e0d 100644 --- a/Commander/Properties/AssemblyInfo.cs +++ b/Commander/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Keeper Security Inc.")] [assembly: AssemblyProduct(".NET Commander")] -[assembly: AssemblyCopyright("Copyright (c) 2023")] +[assembly: AssemblyCopyright("Copyright (c) 2024")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.1.3")] -[assembly: AssemblyFileVersion("1.0.1.3")] +[assembly: AssemblyVersion("1.0.1.5")] +[assembly: AssemblyFileVersion("1.0.1.5")] diff --git a/Commander/enterprise/EnterpriseCommands.cs b/Commander/enterprise/EnterpriseCommands.cs index 5f8697c..d59f0a8 100644 --- a/Commander/enterprise/EnterpriseCommands.cs +++ b/Commander/enterprise/EnterpriseCommands.cs @@ -27,7 +27,7 @@ internal interface IEnterpriseContext { EnterpriseLoader Enterprise { get; } EnterpriseData EnterpriseData { get; } - RoleDataManagement RoleManagement { get; } + RoleData RoleManagement { get; } QueuedTeamDataManagement QueuedTeamManagement { get; } UserAliasData UserAliasData { get; } @@ -761,7 +761,7 @@ public static async Task ExtendAccountShareExpirationCommand(this IEnterpriseCon private static string[] _privilegeNames = new string[] { "MANAGE_NODES", "MANAGE_USER", "MANAGE_ROLES", "MANAGE_TEAMS", "RUN_REPORTS", "MANAGE_BRIDGE", "APPROVE_DEVICE", "TRANSFER_ACCOUNT" }; - public static async Task EnterpriseRoleCommand(this RoleDataManagement roleData, EnterpriseData enterpriseData, EnterpriseRoleOptions arguments) + public static async Task EnterpriseRoleCommand(this RoleData roleData, EnterpriseData enterpriseData, EnterpriseRoleOptions arguments) { if (arguments.Force) { @@ -928,7 +928,7 @@ public static async Task EnterpriseRoleCommand(this RoleDataManagement roleData, nodeId = enterpriseData.RootNode.Id; } - await roleData.CreateRole(arguments.Role, nodeId, arguments.VisibleBelow, arguments.NewUser); + await roleData.CreateRole(arguments.Role, nodeId, arguments.NewUser); Console.WriteLine($"Role \"{arguments.Role}\" successfully added."); return; } @@ -1028,7 +1028,7 @@ public static async Task EnterpriseRoleCommand(this RoleDataManagement roleData, if (string.CompareOrdinal(arguments.Command, "delete") == 0) { - await roleData.DeleteRole(role.Id); + await roleData.DeleteRole(role); return; } @@ -1088,11 +1088,11 @@ public static async Task EnterpriseRoleCommand(this RoleDataManagement roleData, Console.Write($"User: \"{user.Email}\" : "); if (isAdd) { - await roleData.AddUserToRole(role.Id, user.Id); + await roleData.AddUserToRole(role, user); } else { - await roleData.RemoveUserFromRole(role.Id, user.Id); + await roleData.RemoveUserFromRole(role, user); } Console.WriteLine("Success"); } @@ -1108,11 +1108,11 @@ public static async Task EnterpriseRoleCommand(this RoleDataManagement roleData, Console.Write($"Team: \"{team.Name}\" : "); if (isAdd) { - await roleData.AddTeamToRole(role.Id, team.Uid); + await roleData.AddTeamToRole(role, team); } else { - await roleData.RemoveTeamFromRole(role.Id, team.Uid); + await roleData.RemoveTeamFromRole(role, team); } Console.WriteLine("Success"); } @@ -1850,7 +1850,7 @@ internal class McEnterpriseContext : StateCommands, IEnterpriseContext public EnterpriseLoader Enterprise { get; } public EnterpriseData EnterpriseData { get; } public DeviceApprovalData DeviceApproval { get; } - public RoleDataManagement RoleManagement { get; } + public RoleData RoleManagement { get; } public QueuedTeamDataManagement QueuedTeamManagement { get; } public UserAliasData UserAliasData { get; } @@ -1859,7 +1859,7 @@ public McEnterpriseContext(ManagedCompanyAuth auth) if (auth.AuthContext.IsEnterpriseAdmin) { DeviceApproval = new DeviceApprovalData(); - RoleManagement = new RoleDataManagement(); + RoleManagement = new RoleData(); EnterpriseData = new EnterpriseData(); QueuedTeamManagement = new QueuedTeamDataManagement(); UserAliasData = new UserAliasData(); @@ -1896,7 +1896,7 @@ public partial class ConnectedContext : IEnterpriseContext { public EnterpriseLoader Enterprise { get; private set; } public EnterpriseData EnterpriseData { get; private set; } - public RoleDataManagement RoleManagement { get; private set; } + public RoleData RoleManagement { get; private set; } public QueuedTeamDataManagement QueuedTeamManagement { get; private set; } public UserAliasData UserAliasData { get; internal set; } @@ -1915,7 +1915,7 @@ private void CheckIfEnterpriseAdmin() if (_auth.AuthContext.IsEnterpriseAdmin) { EnterpriseData = new EnterpriseData(); - RoleManagement = new RoleDataManagement(); + RoleManagement = new RoleData(); DeviceApproval = new DeviceApprovalData(); _managedCompanies = new ManagedCompanyData(); QueuedTeamManagement = new QueuedTeamDataManagement(); @@ -2308,9 +2308,6 @@ class EnterpriseRoleOptions : EnterpriseGenericOptions [Option("node", Required = false, HelpText = "Node Name or ID. \"add\"")] public string Node { get; set; } - [Option('b', "visible-below", Required = false, Default = true, HelpText = "Visible to all nodes in hierarchy below. \"add\"")] - public bool VisibleBelow { get; set; } - [Option('n', "new-user", Required = false, Default = false, HelpText = "New users automatically get this role assigned. \"add\"")] public bool NewUser { get; set; } diff --git a/Commander/enterprise/RoleDataManagement.cs b/Commander/enterprise/RoleDataManagement.cs deleted file mode 100644 index 48e2163..0000000 --- a/Commander/enterprise/RoleDataManagement.cs +++ /dev/null @@ -1,120 +0,0 @@ -using KeeperSecurity.Commands; -using KeeperSecurity.Authentication; -using System.Threading.Tasks; -using KeeperSecurity.Utils; -using Enterprise; -using Google.Protobuf; -using KeeperSecurity.Enterprise; - -namespace Commander.Enterprise -{ - public interface IRoleDataManagement : IRoleData - { - Task CreateRole(string roleName, long nodeId, bool visibleBelow, bool newUserInherit); - Task DeleteRole(long roleId); - - Task AddUserToRole(long roleId, long userId); - Task AddUserToAdminRole(long roleId, long userId, byte[] userRsaPublicKey); - Task RemoveUserFromRole(long roleId, long userId); - Task AddTeamToRole(long roleId, string teamUid); - Task RemoveTeamFromRole(long roleId, string teamUid); - } - - public class RoleDataManagement : RoleData, IRoleDataManagement - { - public async Task CreateRole(string roleName, long nodeId, bool visibleBelow, bool newUserInherit) - { - var encryptedData = new EncryptedData - { - DisplayName = roleName - }; - - var roleId = await Enterprise.GetEnterpriseId(); - var rq = new RoleAddCommand - { - RoleId = roleId, - NodeId = nodeId, - EncryptedData = EnterpriseUtils.EncryptEncryptedData(encryptedData, Enterprise.TreeKey), - VisibleBelow = visibleBelow, - NewUserInherit = newUserInherit - }; - - await Enterprise.Auth.ExecuteAuthCommand(rq); - await Enterprise.Load(); - return TryGetRole(roleId, out var role) ? role : null; - } - - public async Task DeleteRole(long roleId) - { - await Enterprise.Auth.ExecuteAuthCommand(new RoleDeleteCommand { RoleId = roleId }); ; - await Enterprise.Load(); - } - - public async Task AddUserToRole(long roleId, long userId) - { - var rq = new RoleUserAddCommand - { - RoleId = roleId, - EnterpriseUserId = userId, - }; - - await Enterprise.Auth.ExecuteAuthCommand(rq); - await Enterprise.Load(); - } - - public async Task AddUserToAdminRole(long roleId, long userId, byte[] userRsaPublicKey) - { - var publicKey = CryptoUtils.LoadPublicKey(userRsaPublicKey); - var rq = new RoleUserAddCommand - { - RoleId = roleId, - EnterpriseUserId = userId, - TreeKey = CryptoUtils.EncryptRsa(Enterprise.TreeKey, publicKey).Base64UrlEncode(), - }; - var roleKey = await GetRoleKey(roleId); - if (roleKey != null) - { - rq.RoleAdminKey = CryptoUtils.EncryptRsa(roleKey, publicKey).Base64UrlEncode(); - } - await Enterprise.Auth.ExecuteAuthCommand(rq); - await Enterprise.Load(); - } - - public async Task RemoveUserFromRole(long roleId, long userId) - { - var rq = new RoleUserRemoveCommand - { - RoleId = roleId, - EnterpriseUserId = userId, - }; - - await Enterprise.Auth.ExecuteAuthCommand(rq); - await Enterprise.Load(); - } - - public async Task AddTeamToRole(long roleId, string teamUid) { - var rq = new RoleTeams(); - rq.RoleTeam.Add(new RoleTeam - { - RoleId = roleId, - TeamUid = ByteString.CopyFrom(teamUid.Base64UrlDecode()), - }); - - await Enterprise.Auth.ExecuteAuthRest("enterprise/role_team_add", rq); - await Enterprise.Load(); - } - - public async Task RemoveTeamFromRole(long roleId, string teamUid) - { - var rq = new RoleTeams(); - rq.RoleTeam.Add(new RoleTeam - { - RoleId = roleId, - TeamUid = ByteString.CopyFrom(teamUid.Base64UrlDecode()), - }); - - await Enterprise.Auth.ExecuteAuthRest("enterprise/role_team_remove", rq); - await Enterprise.Load(); - } - } -} diff --git a/KeeperSdk/KeeperSdk.csproj b/KeeperSdk/KeeperSdk.csproj index 77e5baa..ef57177 100644 --- a/KeeperSdk/KeeperSdk.csproj +++ b/KeeperSdk/KeeperSdk.csproj @@ -3,7 +3,7 @@ netstandard2.0;net452 7.1 - 1.0.6-beta01 + 1.0.6-beta02 Keeper Security Inc. .NET Keeper Sdk keeper password manager @@ -13,8 +13,8 @@ Github https://github.com/Keeper-Security/keeper-sdk-dotnet false - 1.0.5.33 - 1.0.5.33 + 1.0.6.40 + 1.0.6.40 MIT false true diff --git a/KeeperSdk/enterprise/EnterpriseTypes.cs b/KeeperSdk/enterprise/EnterpriseTypes.cs index efc4dff..190f7e6 100644 --- a/KeeperSdk/enterprise/EnterpriseTypes.cs +++ b/KeeperSdk/enterprise/EnterpriseTypes.cs @@ -94,21 +94,21 @@ public class AccountTransferResult public interface IEnterpriseDataManagement { /// - /// Invides User to Enterprise. + /// Invites a User to Enterprise. /// /// User email /// Invided user options /// Invited User Task InviteUser(string email, InviteUserOptions options = null); /// - /// Locks or Unlocks Enterprise User. + /// Locks or Unlocks an Enterprise User. /// /// Enterprise User /// Lock flag /// User Task SetUserLocked(EnterpriseUser user, bool locked); /// - /// Deletes Enterprise User. + /// Deletes an Enterprise User. /// /// Enterprise User /// Task diff --git a/KeeperSdk/enterprise/RoleData.cs b/KeeperSdk/enterprise/RoleData.cs index 5686b3f..591c4f1 100644 --- a/KeeperSdk/enterprise/RoleData.cs +++ b/KeeperSdk/enterprise/RoleData.cs @@ -9,6 +9,39 @@ namespace KeeperSecurity.Enterprise { + public class RolePermissions + { + const string MANAGE_NODES = "MANAGE_NODES"; + const string MANAGE_USERS = "MANAGE_USER"; + const string MANAGE_ROLES = "MANAGE_ROLES"; + const string MANAGE_TEAMS = "MANAGE_TEAMS"; + const string MANAGE_AUDIT_REPORTS = "RUN_REPORTS"; + const string MANAGE_BRIDGE_SSO = "MANAGE_BRIDGE"; + const string APPROVE_DEVICE = "APPROVE_DEVICE"; + const string MANAGE_RECORD_TYPES = "MANAGE_RECORD_TYPES"; + const string RUN_COMPLIANCE_REPORTS = "RUN_COMPLIANCE_REPORTS"; + const string MANAGE_COMPANIES = "MANAGE_COMPANIES"; + const string TRANSFER_ACCOUNT = "TRANSFER_ACCOUNT"; + const string SHARE_ADMIN = "SHARING_ADMINISTRATOR"; + + internal ISet privileges = new HashSet(StringComparer.InvariantCultureIgnoreCase); + public long RoleId { get; internal set; } + public long NodeId { get; internal set; } + public bool Cascade { get; internal set; } + public bool ManageNodes => privileges.Contains(MANAGE_NODES); + public bool ManageUsers => privileges.Contains(MANAGE_USERS); + public bool ManageRoles => privileges.Contains(MANAGE_ROLES); + public bool ManageTeams => privileges.Contains(MANAGE_TEAMS); + public bool ManageAuditReports => privileges.Contains(MANAGE_AUDIT_REPORTS); + public bool ManageBridgeSso => privileges.Contains(MANAGE_BRIDGE_SSO); + public bool ApproveDevice => privileges.Contains(APPROVE_DEVICE); + public bool ManageRecordTypes => privileges.Contains(MANAGE_RECORD_TYPES); + public bool RunComplianceReports => privileges.Contains(RUN_COMPLIANCE_REPORTS); + public bool ManageCompanies => privileges.Contains(MANAGE_COMPANIES); + public bool TransferAccount => privileges.Contains(TRANSFER_ACCOUNT); + public bool ShareAdmin => privileges.Contains(SHARE_ADMIN); + } + /// /// Defines Role enterprise data. /// @@ -60,6 +93,18 @@ public interface IRoleData /// List of Role Enforcements IEnumerable GetEnforcementsForRole(long roleId); + /// + /// Gets a list of all administrative permissions + /// + /// + IEnumerable GetAdminPermissions(); + /// + /// Gets a list administrative permissions for a role + /// + /// + /// + IEnumerable GetRolePermissions(long roleId); + /// /// Gets role key. /// @@ -71,7 +116,7 @@ public interface IRoleData /// /// Represents Role enterprise data. /// - public class RoleData : EnterpriseDataPlugin, IRoleData + public partial class RoleData : EnterpriseDataPlugin, IRoleData { private readonly RoleDictionary _roles = new RoleDictionary(); private readonly RoleUserLink _roleUsers = new RoleUserLink(); @@ -131,6 +176,36 @@ public IEnumerable GetEnforcementsForRole(long roleId) return _roleEnforcements.LinksForPrimaryKey(roleId); } + internal RolePermissions GetRolePermission(ManagedNode managedNode) + { + var rp = new RolePermissions + { + RoleId = managedNode.RoleId, + NodeId = managedNode.ManagedNodeId, + Cascade = managedNode.CascadeNodeManagement + }; + + foreach (var p in GetPrivilegesForRoleAndNode(rp.RoleId, rp.NodeId)) + { + rp.privileges.Add(p.PrivilegeType); + } + return rp; + } + public IEnumerable GetAdminPermissions() + { + foreach (var p in GetManagedNodes()) { + yield return GetRolePermission(p); + } + } + + public IEnumerable GetRolePermissions(long roleId) + { + foreach (var p in _managedNodes.LinksForPrimaryKey(roleId)) + { + yield return GetRolePermission(p); + } + } + /// /// Gets a list of privileges for specified role and node /// @@ -266,8 +341,11 @@ protected override void PopulateSdkFromKeeper(EnterpriseRole sdk, Role keeper) { EnterpriseUtils.DecryptEncryptedData(keeper.EncryptedData, enterprise.TreeKey, sdk); } + if (string.Equals(sdk.RoleType, "pool_manager", StringComparison.InvariantCultureIgnoreCase)) + { + sdk.DisplayName = "MSP Subscription Manager"; + } } - protected override void SetEntityId(EnterpriseRole entity, long id) { entity.Id = id; @@ -337,6 +415,8 @@ protected override string GetEntity2Id(RoleEnforcement keeperData) } } + ///////// + /// public class ManagedNodeLink : EnterpriseDataLink { diff --git a/KeeperSdk/enterprise/RoleManagement.cs b/KeeperSdk/enterprise/RoleManagement.cs new file mode 100644 index 0000000..0bca293 --- /dev/null +++ b/KeeperSdk/enterprise/RoleManagement.cs @@ -0,0 +1,177 @@ +using Enterprise; +using Google.Protobuf; +using KeeperSecurity.Authentication; +using KeeperSecurity.Commands; +using KeeperSecurity.Utils; +using System.Linq; +using System.Threading.Tasks; + +namespace KeeperSecurity.Enterprise +{ + /// + /// Defines methods for managing enerprise roles + /// + public interface IRoleDataManagement + { + /// + /// Creates Enterprise Role + /// + /// Role name + /// Role's node ID + /// Set role as default for new users + /// Created role + Task CreateRole(string roleName, long nodeId, bool newUserInherit); + /// + /// Deletes Enterprise Role + /// + /// Enterprise role + /// Task + Task DeleteRole(EnterpriseRole role); + /// + /// Add a user to a role + /// + /// Enterprise roler + /// Enterprise user + /// Task + Task AddUserToRole(EnterpriseRole role, EnterpriseUser user); + /// + /// Adds a user to Admin role + /// + /// Enterprise role + /// Enterprise user + /// Task + Task AddUserToAdminRole(EnterpriseRole role, EnterpriseUser user); + /// + /// Removes a user from a role + /// + /// Enterprise role + /// Enterprise user + /// Task + Task RemoveUserFromRole(EnterpriseRole role, EnterpriseUser user); + /// + /// Adds a team to a role + /// + /// Enterprise role + /// Enterprise team + /// Task + Task AddTeamToRole(EnterpriseRole role, EnterpriseTeam team); + /// + /// Removes a team from a role + /// + /// Enterprise role + /// Enterprise team + /// Task + Task RemoveTeamFromRole(EnterpriseRole role, EnterpriseTeam team); + } + + public partial class RoleData : IRoleDataManagement + { + /// + public async Task CreateRole(string roleName, long nodeId, bool newUserInherit) + { + var encryptedData = new EncryptedData + { + DisplayName = roleName + }; + + var roleId = await Enterprise.GetEnterpriseId(); + var rq = new RoleAddCommand + { + RoleId = roleId, + NodeId = nodeId, + EncryptedData = EnterpriseUtils.EncryptEncryptedData(encryptedData, Enterprise.TreeKey), + NewUserInherit = newUserInherit + }; + + await Enterprise.Auth.ExecuteAuthCommand(rq); + await Enterprise.Load(); + return TryGetRole(roleId, out var role) ? role : null; + } + + /// + public async Task DeleteRole(EnterpriseRole role) + { + await Enterprise.Auth.ExecuteAuthCommand(new RoleDeleteCommand { RoleId = role.Id }); ; + await Enterprise.Load(); + } + + /// + public async Task AddUserToRole(EnterpriseRole role, EnterpriseUser user) + { + var rq = new RoleUserAddCommand + { + RoleId = role.Id, + EnterpriseUserId = user.Id, + }; + + await Enterprise.Auth.ExecuteAuthCommand(rq); + await Enterprise.Load(); + } + + /// + public async Task AddUserToAdminRole(EnterpriseRole role, EnterpriseUser user) + { + + await Enterprise.Auth.LoadUsersKeys(Enumerable.Repeat(user.Email, 1)); + if (!Enterprise.Auth.TryGetUserKeys(user.Email, out var keys)) + { + throw new System.Exception($"User ${user.Email}: public key is not available"); + } + var publicKey = CryptoUtils.LoadPublicKey(keys.RsaPublicKey); + var rq = new RoleUserAddCommand + { + RoleId = role.Id, + EnterpriseUserId = user.UserId, + TreeKey = CryptoUtils.EncryptRsa(Enterprise.TreeKey, publicKey).Base64UrlEncode(), + }; + var roleKey = await GetRoleKey(role.Id); + if (roleKey != null) + { + rq.RoleAdminKey = CryptoUtils.EncryptRsa(roleKey, publicKey).Base64UrlEncode(); + } + await Enterprise.Auth.ExecuteAuthCommand(rq); + await Enterprise.Load(); + } + + /// + public async Task RemoveUserFromRole(EnterpriseRole role, EnterpriseUser user) + { + var rq = new RoleUserRemoveCommand + { + RoleId = role.Id, + EnterpriseUserId = user.Id, + }; + + await Enterprise.Auth.ExecuteAuthCommand(rq); + await Enterprise.Load(); + } + + /// + public async Task AddTeamToRole(EnterpriseRole role, EnterpriseTeam team) + { + var rq = new RoleTeams(); + rq.RoleTeam.Add(new RoleTeam + { + RoleId = role.Id, + TeamUid = ByteString.CopyFrom(team.Uid.Base64UrlDecode()), + }); + + await Enterprise.Auth.ExecuteAuthRest("enterprise/role_team_add", rq); + await Enterprise.Load(); + } + + /// + public async Task RemoveTeamFromRole(EnterpriseRole role, EnterpriseTeam team) + { + var rq = new RoleTeams(); + rq.RoleTeam.Add(new RoleTeam + { + RoleId = role.Id, + TeamUid = ByteString.CopyFrom(team.Uid.Base64UrlDecode()), + }); + + await Enterprise.Auth.ExecuteAuthRest("enterprise/role_team_remove", rq); + await Enterprise.Load(); + } + } +} diff --git a/PowerCommander/Enterprise.format.ps1xml b/PowerCommander/Enterprise.format.ps1xml index 85d857c..c9c9a4d 100644 --- a/PowerCommander/Enterprise.format.ps1xml +++ b/PowerCommander/Enterprise.format.ps1xml @@ -323,7 +323,20 @@ - + + + Center + + + Center + + + Center + + + + Center + @@ -336,10 +349,23 @@ DisplayName - ParentNodeName + NodeName - NewUserInherit + + if ($_.NewUserInherit -eq $true) {'X'} else {'-'} + + + + Users + + + Teams + + + + if ($_.IsAdminRole -eq $true) {'X'} else {'-'} + @@ -365,16 +391,120 @@ ParentNodeId - ParentNodeName + NodeName NewUserInherit + + UserList + + + TeamList + + + KeeperSecurity.Enterprise.RolePermissions_TableView + + KeeperSecurity.Enterprise.RolePermissions + + + + + + + + Center + + + + Center + + + + Center + + + + Center + + + + Center + + + + Center + + + + Center + + + + Center + + + + + + + + RoleName + + + NodeName + + + + if ($_.Cascade -eq $true) {'X'} else {'-'} + + + + + if ($_.ManageNodes -eq $true) {'X'} else {'-'} + + + + + if ($_.ManageUsers -eq $true) {'X'} else {'-'} + + + + + if ($_.ManageRoles -eq $true) {'X'} else {'-'} + + + + + if ($_.ManageTeams -eq $true) {'X'} else {'-'} + + + + + if ($_.ManageCompanies -eq $true) {'X'} else {'-'} + + + + + if ($_.ShareAdmin -eq $true) {'X'} else {'-'} + + + + + if ($_.TransferAccount -eq $true) {'X'} else {'-'} + + + + + + + + \ No newline at end of file diff --git a/PowerCommander/Enterprise.ps1 b/PowerCommander/Enterprise.ps1 index af5d709..d71cd7f 100644 --- a/PowerCommander/Enterprise.ps1 +++ b/PowerCommander/Enterprise.ps1 @@ -539,8 +539,11 @@ New-Alias -Name ken -Value Get-KeeperEnterpriseNode function Get-KeeperEnterpriseRole { <# - .Synopsis + .SYNOPSIS Get a list of enterprise roles + + .PARAMETER Role + Role Name or ID #> [CmdletBinding()] @@ -548,3 +551,224 @@ function Get-KeeperEnterpriseRole { return $enterprise.roleData.Roles } New-Alias -Name ker -Value Get-KeeperEnterpriseRole + +$Keeper_RoleNameCompleter = { + param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) + + $result = @() + [Enterprise]$enterprise = $Script:Context.Enterprise + if (-not $enterprise) { + return $null + } + if ($wordToComplete) { + $to_complete = $wordToComplete + '*' + } + else { + $to_complete = '*' + } + foreach ($role in $enterprise.roleData.Roles) { + if ($role.DisplayName -like $to_complete) { + $roleName = $role.DisplayName + if ($roleName -match '[\s'']') { + $roleName = $roleName -replace '''', '''''' + $roleName = "'${roleName}'" + } + + $result += $roleName + } + } + if ($result.Count -gt 0) { + return $result + } + else { + return $null + } +} + +function Get-KeeperEnterpriseRoleUsers { + <# + .SYNOPSIS + Get a list of enterprise users for a role + + .PARAMETER Role + Role Name or ID + #> + [CmdletBinding()] + Param ( + [Parameter(Position = 0, Mandatory = $true)]$Role + ) + + [Enterprise]$enterprise = getEnterprise + $enterpriseData = $enterprise.enterpriseData + $roleData = $enterprise.roleData + $roleId = $null + + if ($Role -is [String]) { + $ids = Get-KeeperEnterpriseRole | Where-Object { $_.Id -eq $Role -or $_.DisplayName -ieq $Role } | Select-Object -Property Id + if ($ids.Length -gt 1) { + Write-Error -Message "Role name `"$Role`" is not unique. Use Role ID" -ErrorAction Stop + } + + if ($null -ne $ids.Id) { + $roleId = $ids.Id + } + } + elseif ($Role -is [long]) { + $ids = Get-KeeperEnterpriseRole | Where-Object { $_.Id -ceq $Role } | Select-Object -First 1 + if ($ids.Length -eq 1) { + $roleId = $ids[0].Id + } + } + elseif ($null -ne $Role.Id) { + $roleId = $Role.Id + } + if ($roleId) { + $erole = $null + if ($roleData.TryGetRole($roleId, [ref]$erole)) { + foreach ($userId in $roleData.GetUsersForRole($erole.Id)) { + $user = $null + if ($enterpriseData.TryGetUserById($userId, [ref]$user)) { + $user + } + } + } + else { + Write-Error -Message "Role `"$roleId`" not found" -ErrorAction Stop + } + } + else { + Write-Error -Message "Role `"$Role`" not found" -ErrorAction Stop + } +} +New-Alias -Name keru -Value Get-KeeperEnterpriseRoleUsers +Register-ArgumentCompleter -CommandName Get-KeeperEnterpriseRoleUsers -ParameterName Role -ScriptBlock $Keeper_RoleNameCompleter + +function Get-KeeperEnterpriseRoleTeams { + <# + .SYNOPSIS + Get a list of enterprise teams for a role + + .PARAMETER Role + Role Name or ID + #> + [CmdletBinding()] + Param ( + [Parameter(Position = 0, Mandatory = $true)]$Role + ) + + [Enterprise]$enterprise = getEnterprise + $enterpriseData = $enterprise.enterpriseData + $roleData = $enterprise.roleData + $roleId = $null + + if ($Role -is [String]) { + $ids = Get-KeeperEnterpriseRole | Where-Object { $_.Id -eq $Role -or $_.DisplayName -ieq $Role } | Select-Object -Property Id + if ($ids.Length -gt 1) { + Write-Error -Message "Role name `"$Role`" is not unique. Use Role ID" -ErrorAction Stop + } + + if ($null -ne $ids.Id) { + $roleId = $ids.Id + } + } + elseif ($Role -is [long]) { + $ids = Get-KeeperEnterpriseRole | Where-Object { $_.Id -ceq $Role } | Select-Object -First 1 + if ($ids.Length -eq 1) { + $roleId = $ids[0].Id + } + } + elseif ($null -ne $Role.Id) { + $roleId = $Role.Id + } + if ($roleId) { + $erole = $null + if ($roleData.TryGetRole($roleId, [ref]$erole)) { + foreach ($teamUid in $roleData.GetTeamsForRole($erole.Id)) { + $team = $null + if ($enterpriseData.TryGetTeam($teamUid, [ref]$team)) { + $team + } + } + } + else { + Write-Error -Message "Role `"$roleId`" not found" -ErrorAction Stop + } + } + else { + Write-Error -Message "Role `"$Role`" not found" -ErrorAction Stop + } +} +New-Alias -Name kert -Value Get-KeeperEnterpriseRoleTeams +Register-ArgumentCompleter -CommandName Get-KeeperEnterpriseRoleTeams -ParameterName Role -ScriptBlock $Keeper_RoleNameCompleter + +function Get-KeeperEnterpriseAdminRole { + <# + .SYNOPSIS + Get a list of Administrator Permissions + + .PARAMETER Pattern + Role search pattern + #> + [CmdletBinding()] + Param ( + [Parameter(Position = 0, Mandatory = $false)]$Pattern + ) + + [Enterprise]$enterprise = getEnterprise + $roleData = $enterprise.roleData + $roles = $null + + if ($Pattern -is [String]) { + $roles = Get-KeeperEnterpriseRole | Where-Object { $_.Id -eq $Pattern -or $_.DisplayName -match $Pattern } + } + elseif ($Pattern -is [long]) { + $roles = Get-KeeperEnterpriseRole | Where-Object { $_.Id -eq $Pattern } + } + elseif ($null -ne $Pattern.Id) { + $roles = $Pattern + } + else { + $roles = Get-KeeperEnterpriseRole + } + if ($null -ne $roles -and $roles.Length -gt 0 ) { + $roles = $roles | Sort-Object -Property DisplayName + foreach ($role in $roles) { + if ($null -ne $role.Id) { + foreach ($rp in $roleData.GetRolePermissions($role.Id)) { + $rp + } + } + } + } + else { + Write-Error -Message "Role `"$Role`" not found" -ErrorAction Stop + } +} +New-Alias -Name kerap -Value Get-KeeperEnterpriseAdminRole + +function Script:Get-KeeperNodeName { + Param ( + [long]$nodeId + ) + $enterprise = getEnterprise + [KeeperSecurity.Enterprise.EnterpriseNode]$node = $null + if ($enterprise.enterpriseData.TryGetNode($nodeId, [ref]$node)) { + if ($node.ParentNodeId -gt 0) { + return $node.DisplayName + } + else { + return $enterprise.loader.EnterpriseName + } + } +} + +function Script:Get-KeeperRoleName { + Param ( + [long]$roleId + ) + $enterprise = getEnterprise + [KeeperSecurity.Enterprise.EnterpriseRole]$role = $null + if ($enterprise.roleData.TryGetRole($roleId, [ref]$role)) { + return $role.DisplayName + } +} diff --git a/PowerCommander/Enterprise.types.ps1xml b/PowerCommander/Enterprise.types.ps1xml index f6d65c7..2517bf8 100644 --- a/PowerCommander/Enterprise.types.ps1xml +++ b/PowerCommander/Enterprise.types.ps1xml @@ -104,7 +104,7 @@ Allocated - NumberOfSeats + NumberOfSeats @@ -112,11 +112,67 @@ KeeperSecurity.Enterprise.EnterpriseRole - ParentNodeName + NodeName Get-KeeperNodeName $this.ParentNodeId + + Users + + (Get-KeeperEnterpriseRoleUsers $this.Id).Count + + + + Teams + + (Get-KeeperEnterpriseRoleTeams $this.Id).Count + + + + IsAdminRole + + (Get-KeeperEnterpriseAdminRole $this.Id).Count -gt 0 + + + + UserList + + $users = @() + foreach ($user in Get-KeeperEnterpriseRoleUsers $this.Id) { + $users += $user.Email + } + $users -join "`r`n" + + + + TeamList + + $teams = @() + foreach ($team in Get-KeeperEnterpriseRoleTeams $this.Id) { + $teams += $team.Name + } + $teams -join "`r`n" + + + + + + + KeeperSecurity.Enterprise.RolePermissions + + + NodeName + + Get-KeeperNodeName $this.NodeId + + + + RoleName + + Get-KeeperRoleName $this.RoleId + + diff --git a/PowerCommander/ManagedCompany.ps1 b/PowerCommander/ManagedCompany.ps1 index f8df33a..4503e94 100644 --- a/PowerCommander/ManagedCompany.ps1 +++ b/PowerCommander/ManagedCompany.ps1 @@ -367,22 +367,6 @@ function Get-MspBillingReport { } } -function Script:Get-KeeperNodeName { - Param ( - [long]$nodeId - ) - $enterprise = getEnterprise - [KeeperSecurity.Enterprise.EnterpriseNode]$node = $null - if ($enterprise.enterpriseData.TryGetNode($nodeId, [ref]$node)) { - if ($node.ParentNodeId -gt 0) { - return $node.DisplayName - } - else { - return $enterprise.loader.EnterpriseName - } - } -} - function findManagedCompany { Param ( [string]$mc diff --git a/PowerCommander/PowerCommander.psd1 b/PowerCommander/PowerCommander.psd1 index 2614e5e..8f3ecd5 100644 --- a/PowerCommander/PowerCommander.psd1 +++ b/PowerCommander/PowerCommander.psd1 @@ -11,7 +11,7 @@ RootModule = 'PowerCommander.psm1' # Version number of this module. - ModuleVersion = '0.9.15' + ModuleVersion = '0.9.16' # Supported PSEditions CompatiblePSEditions = @('Desktop') @@ -75,9 +75,11 @@ 'Get-KeeperChildItem', 'Get-KeeperObject', 'Get-KeeperRecord', 'Copy-KeeperToClipboard', 'Show-TwoFactorCode', 'Add-KeeperRecord', 'Remove-KeeperRecord', 'Move-RecordToFolder', 'Get-KeeperPasswordVisible', 'Set-KeeperPasswordVisible', 'Get-KeeperSharedFolder', 'Add-KeeperFolder', 'Remove-KeeperFolder', 'Get-KeeperRecordType', - 'Get-KeeperEnterpriseUser', 'Get-KeeperEnterpriseTeam', 'Sync-KeeperEnterprise', 'Get-KeeperEnterpriseNode', 'Get-KeeperNodeName', + 'Get-KeeperEnterpriseUser', 'Get-KeeperEnterpriseTeam', 'Sync-KeeperEnterprise', 'Get-KeeperEnterpriseNode', + 'Get-KeeperNodeName', 'Get-KeeperRoleName', 'Add-KeeperEnterpriseUser', 'Lock-KeeperEnterpriseUser', 'Unlock-KeeperEnterpriseUser', 'Move-KeeperEnterpriseUser', - 'Remove-KeeperEnterpriseUser', 'New-KeeperEnterpriseNode', 'Get-KeeperEnterpriseRole', + 'Remove-KeeperEnterpriseUser', 'New-KeeperEnterpriseNode', 'Get-KeeperEnterpriseRole', 'Get-KeeperEnterpriseRoleUsers', + 'Get-KeeperEnterpriseRoleTeams', 'Get-KeeperEnterpriseAdminRole', 'Get-KeeperManagedCompany', 'New-KeeperManagedCompany', 'Remove-KeeperManagedCompany', 'Edit-KeeperManagedCompany', 'Get-MspBillingReport', 'Switch-KeeperMC', 'Switch-KeeperMSP', 'Get-KeeperEnterpriseTeamUser', 'Get-KeeperInformation', 'Get-KeeperDeviceSettings', 'Set-KeeperDeviceSettings', @@ -97,9 +99,9 @@ # Aliases to export from this module AliasesToExport = @('kc', 'ks', 'kq', 'kpwd', 'kcd', 'kdir', 'ko', 'kr', 'ksf', 'kcc', '2fa', 'kadd', 'kdel', 'kmv', 'kmkdir', 'krmdir', 'krti', - 'ked', 'keu', 'ken', 'ket', 'ker', 'ketu', 'kmc', 'kamc', 'krmc', 'kemc', 'kena', 'msp-license', 'switch-to-mc', 'switch-to-msp', - 'invite-user', 'lock-user', 'unlock-user', 'transfer-user', 'delete-user', 'kshrsh', 'kshr', 'kushr', 'kshf', 'kushf', - 'kat', 'ktr', 'kotsr', 'kotsg', 'kotsn', 'kwhoami', 'this-device', + 'ked', 'keu', 'ken', 'ket', 'ker', 'ketu', 'keru', 'kert', 'kerap', 'kmc', 'kamc', 'krmc', 'kemc', 'kena', 'msp-license', + 'switch-to-mc', 'switch-to-msp', 'invite-user', 'lock-user', 'unlock-user', 'transfer-user', 'delete-user', + 'kshrsh', 'kshr', 'kushr', 'kshf', 'kushf', 'kat', 'ktr', 'kotsr', 'kotsg', 'kotsn', 'kwhoami', 'this-device', 'ksm', 'ksm-create', 'ksm-share', 'ksm-unshare', 'ksm-addclient', 'ksm-rmclient', 'kda') # List of all modules packaged with this module @@ -115,7 +117,7 @@ LicenseUri = 'https://github.com/Keeper-Security/keeper-sdk-dotnet/blob/master/LICENSE' ProjectUri = 'https://github.com/Keeper-Security/keeper-sdk-dotnet' IconUri = 'https://keeper-email-images.s3.amazonaws.com/common/powershell.png' - ReleaseNotes = 'Fix bug in `transfer-user` in MC environment.' + ReleaseNotes = 'Display enterprise role information' } } diff --git a/PowerCommander/PowerCommander.psm1 b/PowerCommander/PowerCommander.psm1 index 03d7d2d..b6776e9 100644 --- a/PowerCommander/PowerCommander.psm1 +++ b/PowerCommander/PowerCommander.psm1 @@ -39,11 +39,15 @@ Export-ModuleMember -Alias ksf Export-ModuleMember -Function Add-KeeperFolder, Remove-KeeperFolder Export-ModuleMember -Alias kmkdir, krmdir +Export-ModuleMember -Function Get-KeeperNodeName, Get-KeeperRoleName + Export-ModuleMember -Function Sync-KeeperEnterprise, Get-KeeperEnterpriseUser, Get-KeeperEnterpriseTeam, -Get-KeeperEnterpriseNode, Get-KeeperNodeName, Add-KeeperEnterpriseUser, Lock-KeeperEnterpriseUser, -Unlock-KeeperEnterpriseUser, Move-KeeperEnterpriseUser, Remove-KeeperEnterpriseUser, -Get-KeeperEnterpriseTeamUser, New-KeeperEnterpriseNode, Get-KeeperEnterpriseRole -Export-ModuleMember -Alias ked, keu, ket, ketu, ken, ker, kena, invite-user, lock-user, unlock-user, transfer-user, delete-user +Get-KeeperEnterpriseNode, Add-KeeperEnterpriseUser, Lock-KeeperEnterpriseUser, +Unlock-KeeperEnterpriseUser, Move-KeeperEnterpriseUser, Remove-KeeperEnterpriseUser, Get-KeeperEnterpriseRoleTeams, +Get-KeeperEnterpriseTeamUser, New-KeeperEnterpriseNode, Get-KeeperEnterpriseRole, Get-KeeperEnterpriseRoleUsers, +Get-KeeperEnterpriseAdminRole +Export-ModuleMember -Alias ked, keu, ket, ketu, ken, ker, keru, kert, kerap, kena, +invite-user, lock-user, unlock-user, transfer-user, delete-user Export-ModuleMember -Function Get-KeeperManagedCompany, New-KeeperManagedCompany, Remove-KeeperManagedCompany, Edit-KeeperManagedCompany, Get-MspBillingReport, Switch-KeeperMC, Switch-KeeperMSP diff --git a/PowerCommander/README.md b/PowerCommander/README.md index 65cbad2..94dc437 100644 --- a/PowerCommander/README.md +++ b/PowerCommander/README.md @@ -65,6 +65,9 @@ To run the PowerCommander module from the source copy PowerCommander\ directory | Move-KeeperEnterpriseUser |transfer-user| Transfer user account to another user | Remove-KeeperEnterpriseUser | delete-user | Delete Enterprise User | Get-KeeperEnterpriseRole | ker | Enumerate all enterprise roles (new) +| Get-KeeperEnterpriseRoleUsers | keru | Get a list of enterprise users for role (new) +| Get-KeeperEnterpriseRoleTeams | kert | Get a list of enterprise teams for role (new) +| Get-KeeperEnterpriseAdminRole | kerap | Enumerate all enterprise role admin permissions (new) | Get-KeeperMspLicenses | msp-license | Return MSP licenses | Switch-KeeperMC |switch-to-mc | Switch to Managed Company (new) | Switch-KeeperMSP |switch-to-msp| Switch back to MSP (new)