Skip to content

Instantly share code, notes, and snippets.

@jimbo8098
Created September 30, 2020 14:45
Show Gist options
  • Save jimbo8098/48fa8d1cd05a61b35534aa107decb3e3 to your computer and use it in GitHub Desktop.
Save jimbo8098/48fa8d1cd05a61b35534aa107decb3e3 to your computer and use it in GitHub Desktop.
Classic ASP Docker Container gMSA

Classic ASP may be almost dead but unfortunately not quite. Thankfully we can at least make it a bit more modern. The steps below go through the steps required to setup gMSA authentication on a Classic ASP docker container. I will use an example of a similar issue I was trying to solve which required Integrated Authentication to be used (in place of plaintext credentials)

  1. Set up your gMSA per https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/manage-serviceaccounts
New-ADGroup -Name "Service Provider Group" -SamAccountName "ServiceHosts" -GroupScope DomainLocal
Add-ADGroupMember -Identity "ServiceHosts" -Members "SERVER01$"
New-ADServiceAccount -Name "app" -DnsHostName "app.domain.local" -ServicePrincipalNames "host/ServiceHosts" - PrincipalsAllowedToRetrieveManagedPassword "ServiceHosts"

Where:

  • "Service Provider Group" is going to be the "human readable" name of the group in AD
  • "ServiceHosts" is the actual name of the group. You add computes to this group to allow them access to get a credspec file
  • "app" is the name of the service account.
  • "app.domain.local" is the FQDN of the service account
  • "host/ServiceHosts" will allow any computer that's part of the ServiceHosts group to use this gMSA
  • "ServiceHosts" are the only objects who are allowed to retrieve the password. This is, in this process, done behind the scenes by IIS/Docker
  1. Make your Dockerfile. I recommend basing on jimbo8098/docker-classic-asp:latest-minimal since this is pre-built with Classic ASP features. Here is a sample file:
FROM jimbo8098/docker-classic-asp:latest-minimal
SHELL ["powershell", "-command"]

RUN powershell -NoProfile -Command Remove-Item -Recurse C:\inetpub\wwwroot\*

ARG SITENAME="testdomain.com"

COPY $SITENAME "C:\\inetpub\\wwwroot\\$SITENAME"

#TODO: Install your DLLS (if any)

RUN Start-IISCommitDelay
RUN New-IISSite -Name "${env:SITENAME}" -BindingInformation "*:80:${env:SITENAME}" -Protocol http -PhysicalPath "C:\inetpub\wwwroot\${env:SITENAME}"
RUN New-IISSiteBinding -name "${env:SITENAME}" -BindingInformation "*:80:www.${env:SITENAME}" -Protocol http
RUN Stop-IISCommitDelay -Commit 1

EXPOSE 80

#Need to do this in one operation. Seperate RUN commands fail to build.
RUN Import-Module WebAdministration; if ($?) {\
    New-WebAppPool –Name "${env:SITENAME}"; if ($?) {\
    Set-ItemProperty "IIS:\AppPools\$env:SITENAME" -name processModel -value @{identitytype=2}; if ($?) {\
    Set-WebConfigurationProperty system.webServer/security/authentication/anonymousAuthentication -Name "userName" -Value \"\"; if ($?) {\
    Set-WebConfigurationProperty system.webServer/security/authentication/anonymousAuthentication -Name "password" -Value \"\"; if ($?) {\
    Set-WebConfigurationProperty system.webServer/security/authentication/anonymousAuthentication -Name "logonMethod" -Value 2; if ($?) {\
    Stop-WebAppPool "$env:SITENAME"; if ($?) {\
    Start-WebAppPool "$env:SITENAME"; }}}}}}}

RUN Import-Module WebAdministration; if ($?) {\
    Set-ItemProperty "IIS:\Sites\$Env:SITENAME" -Name applicationPool -Value $Env:SITENAME; }

WORKDIR /inetpub/wwwroot

This Dockerfile will build your image with the site testdomain.com. The domain will have it's own app pool (with the same name) and the pool and site will be set up with the network service identity. This is perfect for gMSA.

You can look here for some more information on this process:

https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/gmsa-run-container

Build that dockerfile.

  1. Generate your credspec file by logging into the container host and running:
Install-Module CredentialSpec
New-CredentialSpec -AccountName app

This should output your credspec files into C:\ProgramData\docker\CredentialSpecs\ by default. I just left them there. 4. With the credspecs created, you can reference the credspecs either using the format:

--security-opt "credentialspec=file://domain_app.json"

when using a docker run command or, for swarm services, run:

--credential-spec "file://domain_app.json"

Note that the syntax is different in each case. Also that when you use file:// docker will automatically look in the credential spec folder New-CredentialSpec uses by default.

  1. You're done!

Troubleshooting

There are some troubleshooting steps in https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/gmsa-troubleshooting which were very helpful but with IIS you aren't authenticating using the container directly which was a problem I faced earlier in my troubles. I used this .asp script to retrieve the user of the process:

<%
Set objNetwork = CreateObject("WScript.Network")
strNAME = objNetwork.computername
response.write("Value of strNAME variable: " & strNAME & "<br>")
response.write("Domain = " & objNetwork.UserDomain & "<br/>")
response.write("ComputerName = " & objNetwork.ComputerName & "<br/>")
response.write("UserName = " & objNetwork.UserName & "<br/>")
%>

The UserName should be app$ in my example, i.e. the name of your service account. If it's anything else, ensure the application pool and site are both authenticating using the network.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment