12

I have web application that is deployed to my local IIS server under Sites\Default, it works fine and right now I want to make it more secure - I want to encrypt connection strings and appSettings.
Inside pubxml file I've added this line:

<MSDeployEnableWebConfigEncryptRule>true</MSDeployEnableWebConfigEncryptRule>

but that only encrypts connections strings. I know that I can manually call:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -pe "appSettings" -site Default -app "/"

on my server after deploy to encrypt external file containing appSettings, but I must do that manually.

My question is how can I deploy website from Visual Studio (Build > Publish) and have that aspnet_regiis command execute automatically after publish succeeded.

I found information that I could use runcommand and other about bat files, but I'm not calling MSDeploy from command line.
I've also found information that I should build custom provider and call it from MSDeploy.

How should I edit my pubxml file to get this behaviour?

EDIT1:
I've managed to hook After Deploy Target using:

<Target Name="EncryptAppSettings" AfterTargets="MSDeployPublish" >
  <Message Text="Encrypting appSettings" />
  <Exec Command="aspnet_regiis -pe &quot;appSettings&quot; -site Default -app &quot;/&quot;" />
  <Message Text="AppPath: $(DeployIisAppPath)" />
</Target>

But now I get this error:

The command "aspnet_regiis -pe "appSettings" -site Default -app "/"" exited with code 9009.

EDIT2:
I've tried using runCommand like this:

<ItemGroup>
  <MsDeploySourceManifest Include="runCommand">
    <path>aspnet_regiis -pe &quot;appSettings&quot; -site Default -app &quot;/&quot;</path>
    <waitInterval>10000</waitInterval>
    <AdditionalProviderSettings>waitInterval</AdditionalProviderSettings>
  </MsDeploySourceManifest>
</ItemGroup>

but I had no luck. I found blog about postSync:runCommand, but I'd like to call that directly from VS so I'd like to add that to publish profile.

EDIT3:
I'm adding my publish profile below:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <WebPublishMethod>MSDeploy</WebPublishMethod>
    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <SiteUrlToLaunchAfterPublish />
    <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
    <ExcludeApp_Data>False</ExcludeApp_Data>
    <MSDeployServiceURL>192.168.5.50</MSDeployServiceURL>
    <DeployIisAppPath>Default</DeployIisAppPath>
    <RemoteSitePhysicalPath />
    <SkipExtraFilesOnServer>False</SkipExtraFilesOnServer>
    <MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
    <EnableMSDeployBackup>True</EnableMSDeployBackup>
    <MSDeployEnableWebConfigEncryptRule>True</MSDeployEnableWebConfigEncryptRule>
    <UserName>LocalAdmin</UserName>
    <_SavePWD>True</_SavePWD>
    <PublishDatabaseSettings>
      <Objects xmlns="">
        <ObjectGroup Name="ApplicationDbContext" Order="1" Enabled="False">
          <Destination Path="Data Source=192.168.5.51;Initial Catalog=GameBit;User ID=GUser;Password=MyRealPassword;Application Name=EntityFramework" Name="Data Source=192.168.5.51;Initial Catalog=GameBit;User ID=GUser;Password=MyRealPassword;MultipleActiveResultSets=True;Application Name=EntityFramework" />
          <Object Type="DbCodeFirst">
            <Source Path="DBContext" DbContext="Api.ApplicationDbContext, Api" Origin="Configuration" />
          </Object>
        </ObjectGroup>
      </Objects>
    </PublishDatabaseSettings>
  </PropertyGroup>

  <PropertyGroup>
    <UseMsdeployExe>true</UseMsdeployExe>
    <AllowUntrustedCertificate>True</AllowUntrustedCertificate>
  </PropertyGroup>

  <ItemGroup>
    <MSDeployParameterValue Include="$(DeployParameterPrefix)ApplicationDbContext-Web.config Connection String">
      <ParameterValue>metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string="Data Source=192.168.5.51;Initial Catalog=GameBit;User ID=GUser;Password=MyRealPassword;MultipleActiveResultSets=True;Application Name=EntityFramework"</ParameterValue>
    </MSDeployParameterValue>
  </ItemGroup>

  <!--<ItemGroup>
  <MsDeploySourceManifest Include="runCommand">
    <Path>dir</Path>
  </MsDeploySourceManifest>
</ItemGroup>-->


  <!--<Target Name="EncryptImportantSettings" AfterTargets="MSDeployPublish" >
    <Message Text="Encrypting appSettings" />
    --><!--<Exec Command="aspnet_regiis -pe &quot;appSettings&quot; -site Default -app &quot;/&quot;" />--><!--
  <ItemGroup>
    <MsDeploySourceManifest Include="runCommand">
      <path>dir/b >> C:\temp\log.txt</path>
      --><!--<waitInterval>10000</waitInterval>--><!--
      --><!--<AdditionalProviderSettings>waitInterval</AdditionalProviderSettings>--><!--
    </MsDeploySourceManifest>
  </ItemGroup>
  <Message Text="AppPath: $(DeployIisAppPath)" />
  </Target>-->
</Project>

I've noticed that when I use MSDeploy I can see command that is executed during publish:

"C:\Program Files (x86)\IIS\Microsoft Web Deploy V3\msdeploy.exe" -source:manifest='D:\GameBit\API\obj\Release\Package\API.SourceManifest.xml' -dest:auto,ComputerName="https://192.168.5.50:8172/msdeploy.axd?site=Default",UserName='LocalAdmin',Password="MyRealPassword",IncludeAcls='False',AuthType='Basic' -verb:sync -enableRule:EncryptWebConfig -enableRule:EncryptWebConfig -disableLink:AppPoolExtension -disableLink:ContentExtension -disableLink:CertificateExtension -setParamFile:"D:\GameBit\API\obj\Release\Package\API.Publish.Parameters.xml" -allowUntrusted -retryAttempts=2 -userAgent="VS12.0:PublishDialog:WTE12.5.60612.0"

Can I add -postSync:runCommand="" to that command from publish profile? As I found on MS site this parameter allows to execute command on destination machine.

EDIT4:
I found information about Web Deploy Operation Settings and postSync setting, but I don't know where to set it, I don't want to edit Microsoft.Web.Publishing.targets from MSBuild folder

I need to execute command on remote machine after publish succeeded.

Misiu
  • 4,738
  • 21
  • 94
  • 198
  • Hey, I stumbled on this by pure luck. Maybe you should remove one tag and add "asp.net" tag to your question to get more exposure? – HamZa Sep 22 '17 at 08:59
  • 1
    @HamZa thanks for hint. Done. – Misiu Sep 22 '17 at 09:00
  • Use full path to aspnet_regiis and enclose command in quotes ``````. Either command is not place properly on console (*try to echo it and see*) or this file can't be overwritten as something is locking. – SACn Sep 26 '17 at 13:37
  • Sorry. I have created a new question: https://stackoverflow.com/questions/47538285/publish-profile-encryption Please help! – Champ Nov 28 '17 at 18:13

1 Answers1

11

After going through your all edits and a bit of research from me , you want to execute the following command after the publish from the Visual Studio

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -pe "appSettings" -site Default -app "/" 

If i understood right , You can try wrapping the ItemGroup in a Target with AfterTargets set to AddIisSettingAndFileContentsToSourceManifest

<Target Name="executeinHosts" AfterTargets="AddIisSettingAndFileContentsToSourceManifest">
    <ItemGroup>
      <MsDeploySourceManifest Include="runCommand">
         //here would be your path that need to run after the publish
      </MsDeploySourceManifest>
    </ItemGroup>
  </Target>

So in Your case this is how that part should look:

<Target Name="executeinHosts" AfterTargets="AddIisSettingAndFileContentsToSourceManifest">
    <ItemGroup>
      <MsDeploySourceManifest Include="runCommand">
         <path>C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -pe "appSettings" -site $(DeployIisAppPath) -app "/"</path>
      </MsDeploySourceManifest>
    </ItemGroup>
  </Target>

Additional Info:

  • AddIisSettingAndFileContentsToSourceManifest target works justright before Web Deploy copying files from local to server.
  • aspnet_regiis can be run in <target> node by <Exec>.

Ex:

<Exec Command="C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pef connectionStrings $(ProjectDir)obj\Debug\Package\PackageTmp" WorkingDirectory="$(publishUrl)" />
hma
  • 556
  • 2
  • 11
  • 29
Krsna Kishore
  • 8,233
  • 4
  • 32
  • 48
  • Thank You for reply. I remember I've tried adding `MsDeploySourceManifest` but inside VS I got error about namespace `http://schemas.microsoft.com/developer/msbuild/2003`. One additional question, should I put that command inside `path` element inside `MsDeploySourceManifest` or I must escape it somehow? – Misiu Sep 25 '17 at 09:40
  • @Misiu , possibly try with the Path , if it didn't workout need a way to execute it . – Krsna Kishore Sep 25 '17 at 09:50
  • 1
    It worked. `C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -pe "appSettings" -site Default -app "/"` please add this into Your answer so that anyone with similar problem will have working solution. – Misiu Sep 25 '17 at 09:53
  • I was misinformed by that schema warning. One thing missing is getting sine name and path from config instead hard coding them. Do You know how to add them? – Misiu Sep 25 '17 at 09:57
  • I just noticed in Output window that this command runs twice. I got `Encrypting configuration section... Succeeded!` two times. When I remove that target I get no entries, with single target I got two entries in Output. Any ideas why? – Misiu Sep 25 '17 at 10:25
  • @Misiu no idea , might be somewhere triggerring twices in your execution , have a keen look into it – Krsna Kishore Sep 25 '17 at 10:28
  • Nothing fance there. I just added that single new target and I'm still Build>Publish from menu. I'll check that in new project. Maybe I have some changes in csproj. – Misiu Sep 25 '17 at 10:32
  • @Misiu probably MsBUild executing in batches while deploying so ,i'm assuming that time it is executing twice, generally MSbuild will be executing only once thats how functional programming should work.. – Krsna Kishore Sep 25 '17 at 10:51
  • I am trying to do a very similar thing like in this question, but the difference is I am going to deploy my application to the remote server instead of local IIS using Publish>Web Deploy. But I need to encrypt them before copying them over to a server. But haven't found a way to do it. Any suggestion for web deploy? – hma Feb 13 '18 at 16:02
  • by doing right click to project and selecting the publish profile/pubxml file. As a publish option. The profile created by using this option IIS,FTP,ETC option. @Webruster – hma Feb 13 '18 at 17:01
  • @enterbutton which internally uses the process which i defined in my answer – Krsna Kishore Feb 14 '18 at 04:34
  • @Webruster I am pretty new in this so I am trying to understand. Are you referring `` by saying process? And 2more questions when this `AfterTargets="AddIisSettingAndFileContentsToSourceManifest" ` works in publish life cycle ? Which target is working before copying files to a server? So I need to encrypt them before sending them to a server. – hma Feb 14 '18 at 14:20
  • @Webruster Just wanted to update here, `AddIisSettingAndFileContentsToSourceManifest` target is worked just like I needed. It's worked just before copying folders over server. BTW I can also able to run the aspnet_regiis by this command `` rather than using `` – hma Feb 16 '18 at 16:16
  • @enterbutton means ? – Krsna Kishore Feb 16 '18 at 16:21
  • means that it's working just wanted to add here the things I looked into for other people requires more explanation... – hma Feb 16 '18 at 21:06