How to run a Service Fabric application with different security permissions?

Stéphane Bonniez picture Stéphane Bonniez · Aug 24, 2016 · Viewed 7.6k times · Source

Service Fabric RunAs feature

By default, a Service Fabric application will run with the Network Service account. Microsoft has (partial) documentation on how to run it with other permissions: RunAs: Run a Service Fabric application with different security permissions.

Based on this, here's what I'm trying to do:

  • My Service Fabric application calls a library that is being developed in an other repository.
  • When deployed in the cloud, the services will download the binaries for the library from a storage, unzip them in a working directory of the Service Fabric cluster and load it from there.
  • At development time, when I'm testing or debugging the application in a local cluster, I want the binaries for the library to be loaded from some folder on my local hard drive where I have just compiled them, that is right next to the source code.

The tricky part is that my company's security policies require the source code of said library to be accessible only to authorized users, which translates into the folder containing this code being read-protected. As a consequence my Service Fabric application, which runs as Network Service, can't access my binaries. Changing the security policies is not possible, nor giving Network Service access to the folder.

How can I configure my application so that it runs as a user that would have the correct access rights ?

Here's what I already tried:

Using a domain user

The easiest solution would be to be able to run the Service Fabric application with my own login. I tried this by adding the following to my ApplicationManifest.xml:

<Principals>
  <Users>
    <User Name="SfUser" AccountName="Domain\UserName" AccountType="DomainUser" Password="pass" />
  </Users>
</Principals>
<Policies>
  <DefaultRunAsPolicy UserRef="SfUser" />
</Policies>

This works: the application runs as Domain\UserName and can access all the folders I need. But this requires me to put my password in the configuration file, which is not satisfactory.

Using a local user

I then tried using a local user, thinking I would be able to configure access rights correctly using local user groups. The simplest version I could come up with is this:

<Principals>
  <Users>
    <User Name="SfUser" AccountName="LocalSfUser" AccountType="LocalUser">
      <MemberOf>
        <SystemGroup Name="MyLocalGroup"/>
      </MemberOf>
    </User>
  </Users>
</Principals>
<Policies>
  <DefaultRunAsPolicy UserRef="SfUser" />
</Policies>

I think this configuration is correct since when I deploy my application I can see in Windows user manager that several "technical" users where created by Service Fabric and that they belong to MyLocalGroup. However my application never starts.

I noticed several messages in Windows event viewer that seem related to the problem:

Logon Type:               8

Failure Information:
    Failure Reason:       The user has not been granted the requested logon type at this machine.

Process Information:
    Caller Process Name:  C:\Program Files\Microsoft Service Fabric\bin\FabricHost.exe

Apparently, "Logon Type 8" means "Network clear text logon". I suspect a local policy preventing this kind of logon in my company.

Answer

Mark Fussell picture Mark Fussell · Aug 27, 2016

When you run as a localuser, this creates a random local user account on the machine. The reason this is most likely failing in the example above is the <SystemGroup Name="MyLocalGroup"/> needs to be a valid Windows system group such as "Administrators". You also do not really need the AccountName attribute above, but it does no harm.

To solve you issue of getting a file from a remote directory you need to use a domain user as you tried since a local user does not have a shared secret that can be verified with AD. The difference is that you can encrypt the password in the application manifest using a certificate that is deployed to the machine. I have put an example ApplicationManifest.xml snippet below, showing how the password for the domain user is encrypted with a certificate called "MyCert".

<Principals>
  <Users>
    <User Name="TestUser" AccountType="DomainUser" AccountName="Domain\User" Password="[Put Encrypted Password Here" PasswordEncrypted="true" />
  </Users>
</Principals>
<Policies>
  <DefaultRunAsPolicy UserRef="TestUser" />
  <SecurityAccessPolicies>
    <SecurityAccessPolicy ResourceRef="MyCert" PrincipalRef="TestUser" GrantRights="Full" ResourceType="Certificate" />
    </SecurityAccessPolicies>
</Policies>

As a side note the article here https://azure.microsoft.com/en-us/documentation/articles/service-fabric-application-secret-management show how to create the encrypted password in settings.xml which is also often useful.