Имам проблем с извикването на WCF услуга с net.pipe чрез Windows impersonation през C# Windows service.
За какво става въпрос
Услугата чете от опашка и създава дъщерни домейни на приложението, всеки работещ в различен модул, в зависимост от какво е взето от опашката. Windows service-а се казва “JobQueueAgent”, а модулите са “Job”. Всеки модул може да се пусне като отделен потребител. Използваме impersonation вътре в модула, за да го постигнем. Ето как е логическата работа на услугата:
JobQueueAgent (Windows Service – Primary User) >> Създава job domain >> Job Domain (App Domain) >> Impersonate на Sub User >> Пуска модула в нишка с impersonation >> Job (Module – Sub User) >> логика на модула
“Primary User” и “Sub User” са домейн акаунти с права да се логват като услуги.
Услугата върви на виртуален сървър с Windows Server 2012 R2.
Ето и кода за impersonation, който използвам:
namespace JobQueue.WindowsServices
{
using System;
using System.ComponentModel;
using System.Net;
using System.Runtime.InteropServices;
using System.Security.Authentication;
using System.Security.Permissions;
using System.Security.Principal;
internal sealed class ImpersonatedIdentity : IDisposable
{
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public ImpersonatedIdentity(NetworkCredential credential)
{
if (credential == null) throw new ArgumentNullException("credential");
if (LogonUser(credential.UserName, credential.Domain, credential.Password, 5, 0, out _handle))
{
_context = WindowsIdentity.Impersonate(_handle);
}
else
{
throw new AuthenticationException("Impersonation failed.", newWin32Exception(Marshal.GetLastWin32Error()));
}
}
~ImpersonatedIdentity()
{
Dispose();
}
public void Dispose()
{
if (_handle != IntPtr.Zero)
{
CloseHandle(_handle);
_handle = IntPtr.Zero;
}
if (_context != null)
{
_context.Undo();
_context.Dispose();
_context = null;
}
GC.SuppressFinalize(this);
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool LogonUser(string userName, string domain, string password, int logonType,int logonProvider, out IntPtr handle);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
private IntPtr _handle = IntPtr.Zero;
private WindowsImpersonationContext _context;
}
}
Какъв е проблемът
Някои модули изискват да се извика друга Windows услуга,която върви на сървъра, през net.pipe WCF. Net.pipe се чупи докато върви impersonation.
Ето и exception-а, който получавам:
Unhandled Exception: System.ComponentModel.Win32Exception: Access is denied
Server stack trace: at System.ServiceModel.Channels.AppContainerInfo.GetCurrentProcessToken() at System.ServiceModel.Channels.AppContainerInfo.RunningInAppContainer() at System.ServiceModel.Channels.AppContainerInfo.get_IsRunningInAppContainer() at System.ServiceModel.Channels.PipeSharedMemory.BuildPipeName(String pipeGuid)
Net.pipe успява да сработи,когато не минава през impersonation. Успява и когато потребителя,който impersonation-вам е добавен в администраторската група. Това предполага, че потребителя се нуждае от някакви права, за да направи това извикване по време на impersonation. Не можах да разбера какви права или достъп му трябват, за да го направи. Не е приемливо да му се дават администраторски права.
Това известен проблем ли е? Има ли определени права, от които се нуждае потребителя? Какво да променя в кода,за да се оправи?