Prior to ASP.NET Core, it was pretty easy to adjust ACLs in a Web Deploy package with certain MSBuild targets: You would add some custom steps after the AddIisSettingAndFileContentsToSourceManifest
and AddIisAndContentDeclareParametersItems
targets.
Now, in Core, according to my own experiments and issues like this one, these tricks no longer work because
The tasks and targets for ASP.NET Core projects has been re-written ... The target names used in ASP.NET projects are not the same for ASP.NET Core.
I've tried playing with the targets that show up in Microsoft.NET.Sdk.Publish.MSDeployPackage.targets, but I can't seem to make it work. I get this sort of error during package build:
The target "MSDeployPackagePublish" listed in a BeforeTargets attribute ... does not exist in the project, and will be ignored.
What are the new targets? How can I change ACLs in ASP.NET Core Web Deploy projects?
Bafflingly, the Core team appears to have removed the ability to customize the MS Deploy pipeline via MSBuild. These concerns are echoed in several GitHub issues going back to at least 2017, so it appears they have no intention of restoring this feature.
The crux of the problem is the MS Deploy targets have been "simplified for better readability." 😡
The _CreateManifestFiles
target, which used to be made up of several targets between which we could inject our own, now does this:
MsDeploySourceManifest
rules. 😡MsDeploySourceManifest
rules.Likewise, the _CreateParameterFiles
target now does this:
MsDeployDeclareParameters
rules. 😡MsDeployDeclareParameters
rules.Fortunately, there is an extremely terrible workaround to the new locked-down design.
All of the targets are publicly usable, so my solution was just to re-write the _CreateManifestFiles
target with my own -- and overwrite the manifest XML. Here's what I ended up with in my .pubxml
:
<Target Name="ReCreateManifestFile" AfterTargets="_CreateManifestFiles">
<ItemGroup>
<MsDeploySourceManifest Remove="@(MsDeploySourceManifest)" />
<MsDeploySourceManifest Include="IisApp">
<Path>$(PublishIntermediateOutputPath)</Path>
</MsDeploySourceManifest>
<MsDeploySourceManifest Include="setAcl">
<Path>$(PublishIntermediateOutputPath)logs</Path>
<setAclAccess>Read,Write</setAclAccess>
<setAclResourceType>Directory</setAclResourceType>
<AdditionalProviderSettings>setAclAccess;setAclResourceType</AdditionalProviderSettings>
</MsDeploySourceManifest>
</ItemGroup>
<CreateManifestFile Manifests="@(MsDeploySourceManifest)" ManifestFile="$(_MsDeploySourceManifestPath)" />
</Target>
Note that this target executes immediately after _CreateManifestFiles
.
That's the easy part!
I create the parameters file with the same strategy. If you copy _CreateParameterFiles
but add your own MsDeployDeclareParameters
, it does almost does everything you need. Unfortunately, the new SDK also removed the ability for these rules to set ExcludeFromSetParameter
-- if you read the code, that value is never even deserialized. 😡
Without the ability to exclude a parameter from SetParameters.xml, you end up with a SetParameters.xml that looks like this:
<parameters>
<setParameter name="IIS Web Application Name" value="Default Web Site/GeoGrok" />
<setParameter name="LogsSetAclParam" value="" /> <!-- not what you want :( -->
</parameters>
Any parameter in SetParameters.xml can't be ignored at deploy time, even if it has a DefaultValue
. That means MSDeploy won't automatically do the substitution of the IIS App Name if you have a default value of, say, {IIS Web Application Name}/logs
.
MOREOVER, the SDK's CreateParameterFile
call doesn't even include the DeclareParameterFile
attribute, so DefaultValue
is never written to parameters.xml in the first place! 😡
The (again, terrible) solution I went with is:
_CreateParameterFiles
with your own MsDeployDeclareParameters
elements.CreateParameterFile
to create the proper parameters.xml file.My static SetParameters.xml file (which I put in my project root) looks like this:
<?xml version="1.0" encoding="utf-8"?>
<parameters>
<setParameter name="IIS Web Application Name" value="Default Web Site" />
</parameters>
And here's the finished parameters target in my .pubxml
file:
<Target Name="ReCreateParametersFile" AfterTargets="_CreateParameterFiles">
<ItemGroup>
<MsDeployDeclareParameters Remove="@(MsDeployDeclareParameters)" />
<MsDeployDeclareParameters Include="IIS Web Application Name">
<Kind>ProviderPath</Kind>
<Scope>IisApp</Scope>
<Match>$(PublishIntermediateOutputPath)</Match>
<DefaultValue>$(DeployIisAppPath)</DefaultValue>
<Value>$(DeployIisAppPath)</Value>
<Tags>IisApp</Tags>
<Priority></Priority>
<ExcludeFromSetParameter>false</ExcludeFromSetParameter>
</MsDeployDeclareParameters>
<MsDeployDeclareParameters Include="LogsSetAclParam">
<Kind>ProviderPath</Kind>
<Scope>setAcl</Scope>
<Match>$(PublishIntermediateOutputPath)logs</Match>
<DefaultValue>{IIS Web Application Name}/logs</DefaultValue>
<Tags>Hidden</Tags>
<Priority>$(VsSetAclPriority)</Priority>
<ExcludeFromSetParameter>true</ExcludeFromSetParameter> <!-- I'm useless! -->
</MsDeployDeclareParameters>
</ItemGroup>
<CreateParameterFile Parameters="@(MsDeployDeclareParameters)"
DeclareParameterFile="$(_MSDeployParametersFilePath)"
DeclareSetParameterFile="$(_MSDeploySetParametersFilePath)"
IncludeDefaultValue="True"
OptimisticParameterDefaultValue="$(EnableOptimisticParameterDefaultValue)"
SetParameterFile="$(_MSDeploySetParametersFilePath)"
GenerateFileEvenIfEmpty="True" />
<Copy SourceFiles="$(MSBuildProjectDirectory)\GeoGrok.Web.SetParameters.xml" DestinationFiles="$(_MSDeploySetParametersFilePath)" />
</Target>
Note that Copy
step there at the end.
Good luck!