2

I've posted this on stackoverflow, but posting it here as I want some help from folks that are familiar with kerberos delegation and IIS. I am currently trying to figure out how to get my flask app to handle active directory attribute updates on behalf of users in a domain, such as their phone numbers. I currently have this running in IIS 10 on a Windows Server 2019 VM. I have a small virtual lab on Hyper-V that replicates a vanilla Active Directory domain, where I have a domain controller called dc1, a web server called webserver1, and a client machine called client1.

The web application is ran under a service account named service-acct in IIS. Currently, the HTTP request provides me with the windows auth token of the requesting user (via asp net core module), which allows me to impersonate them.

Web.config:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <security>
            <authentication>   
                <anonymousAuthentication enabled="false" />
                <windowsAuthentication enabled="true" useKernelMode="true" useAppPoolCredentials="true" />
            </authentication>
        </security> 
        <handlers>
            <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" requireAccess="Script" />
        </handlers>
        <aspNetCore processPath="C:\apps\Test\venv\scripts\python.exe" arguments="app.py" startupTimeLimit="10" stdoutLogEnabled="true" stdoutLogFile=".\logs\log.log" processesPerApplication="10" forwardWindowsAuthToken="true">
            <environmentVariables>
            </environmentVariables>
        </aspNetCore>
        <httpErrors errorMode="Detailed" />
    </system.webServer>
    <system.web>
        <identity impersonate="true" />
    </system.web>
</configuration>

The workflow looks something like this:

User hits IIS --> Web Server receives HTTP request --> Flask parses the header and gets the windows authentication token --> continue with endpoint python logic

In terms of impersonation, I have been able to use the win32security python module to impersonate the user and perform limited operations within the web server (eg. create folders); however, attempting to update the user's active directory credentials through a flask endpoint leads to a permission error (via the pyad python module):

pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'Active Directory', 'An operations error occurred.\r\n', None, 0, -2147217865), None)

The relevant endpoint python code I used is below:

    @app.route("/TestImpersonation")
    def TestImpersonation():
        key = 'Ms-Aspnetcore-Winauthtoken'
        if key in request.headers.keys():
            handle_str = request.headers[key]
            handle = int(handle_str, 16) # need to convert from Hex / base 16
            win32security.ImpersonateLoggedOnUser(handle)
            user = win32api.GetUserName()

            from pyad import pyad

            user_obj = pyad.from_cn(user)

            description = "Changed by "+ str(user) + " on " + datetime.datetime.today().strftime("%Y/%m/%d %H:%M:%S")
            user_obj.update_attribute('description', description)

            win32security.RevertToSelf() # undo impersonation
            win32api.CloseHandle(handle) # don't leak resources, need to close the handle!
            
        # Continue...

Searching for the error suggests that I have permission issues trying to do the active directory operation, which makes me think it is a double-hop problem. I tried allowing kerberos delegation for the service account in ADUC and also created SPNs for it as such:

setspn -s HTTP/webSERVER1 contoso\service-acct
setspn -s HTTP/webserver1.contoso.com contoso\service-acct

However, that seems to still have issues and I seem to be stuck. Any suggestions?

0

You must log in to answer this question.

Browse other questions tagged .