Azure / azure-libraries-for-net

Azure libraries for .Net
MIT License
377 stars 190 forks source link

IWebApp.GetPublishingProfileAsync() returns null for user/pass when WithFtpsState(FtpsState.FtpsOnly) #1300

Closed daveaglick closed 2 years ago

daveaglick commented 2 years ago

Describe the bug Sometime last week we stopped being able to get username and password credentials for FTP publishing through the fluent API using IWebApp.GetPublishingProfileAsync(). The IPublishingProfile.FtpUsername and IPublishingProfile.FtpPassword are now both coming back as null. It's worth noting that this has worked reliably for at least a year on the exact same web apps until this week.

I was able to track the different back to the use of WithFtpsState(FtpsState.FtpsOnly) when creating an app. For a newly created app without that setting, I could successfully continue to get credentials via IWebApp.GetPublishingProfileAsync(). However, with a brand new app with the WithFtpsState(FtpsState.FtpsOnly) setting, IWebApp.GetPublishingProfileAsync() exhibits the new null username and password behavior.

I've also been able to confirm that the publishing profile, including working username and password, can still be obtained via the REST API using the "/providers/Microsoft.Web/sites/[app name]/publishxml" endpoint. That suggests this is a problem either with the endpoints used by the GetPublishingProfileAsync() method or the method itself in situations where FtpsOnly is turned on.

Exception or Stack Trace No exception is produced, only null IPublishingProfile.FtpUsername and IPublishingProfile.FtpPassword

To Reproduce Call IWebApp.GetPublishingProfileAsync() on a web app with WithFtpsState(FtpsState.FtpsOnly).

Code Snippet

var azure = Microsoft.Azure.Management.Fluent.Azure
    .Configure()
    .Authenticate(credentials)
    .WithSubscription(subscriptionId);
var webapp = await Azure.WebApps.GetByResourceGroupAsync("rg", "appname");
var profile = await webapp.GetPublishingProfileAsync();
profile.FtpUsername.Dump(); // null
profile.FtpPassword.Dump(); // null

Expected behavior A valid username and password for FTP publishing is returned.

Setup (please complete the following information):

Information Checklist Kindly make sure that you have added all the following information above and checkoff the required fields otherwise we will treat the issuer as an incomplete report

Note that I have worked around this problem for our own purposes using the XML publishing profile which still returns expected results.

vlkuznet commented 2 years ago

This line of code contains RegEx that leads to the failure: (https://github.com/Azure/azure-libraries-for-net/blob/master/src/ResourceManagement/AppService/PublishingProfileImpl.cs#L20

Specifically, it matches a publishUrl prefix of ftp://

publishUrl=\"ftp://([^\"]+)

When the App Service FTPS only attribute is enabled, a url with prefix ftps:// is returned. The inclusion of the 's' causes the regex not to match

Sample publish profiles off my app with FTP mode set to "FTPS Only" and "All Allowed", respectively:

FTPS Only: ` ...

... `

All Allowed: ` ...

... `

weidongxu-microsoft commented 2 years ago

@daveaglick @vlkuznet Thanks for the report and analysis. I will fix it in code, but we do not have a schedule on next release as this lib is in maintenance.

A quick workaround is to call

Azure.WebApps.Manager.Inner.WebApps.ListPublishingProfileXmlWithSecretsAsync

and parse the XML.

New user is recommended to switch to https://aka.ms/azsdk/dotnet/mgmt (webapp is not released there yet).