tekitoumemo’s diary

思ったことを書くだけ。長文版Twitter

Azure App Serviceでは.NET Coreの拡張子なしの静的ファイルにアクセス出来ない?

誰の役に立つか不明だが一応。

個人的な都合でLet's Encryptの発行をubuntu機で行っていました。ちょうど入院(え?)したこの機会にmacで発行しようといろいろ試した備忘録です。

いままではLet's EncryptをDNS認証で行っていましたが、今回はACMEチェレンジで試してみました。このチェレンジをするにあたって拡張子なしの静的ファイルにアクセスしなければいけないのでいろいろ思考錯誤しました。

certbotインストール

brew install certbot
certbot --version
certbot 0.39.0

発行申請を出す

sudo certbot certonly --manual --domain example.com
...
Create a file containing just this data:

xxxxxxxxxxxx

And make it available on your web server at this URL:

http://example.com/.well-known/acme-challenge/yyyyy

.well-known/acme-challenge/yyyyyxxxxxxxxxxxxという内容でファイルを置く必要があります。.NET Coreだとセキュリティ上、静的ファイルを気軽に置けません。.NET Coreでは管理外のMINEタイプにアクセスすると404を返す仕様になっています。なので、特定のファイルでもアクセスできるように設定しなければいけません。

StaticFileOptionsのServeUnknownFileTypesプロパティを有効にする

これはすべての静的ファイルが有効になるので非常に危険です。まずやらないほうが良いです。

app.UseStaticFiles(new StaticFileOptions
{
    ServeUnknownFileTypes = true,
});

ローカルでは静的ファイルを返すようになりました。ちなみにホスティングにApp Serviceを使っているのでデプロイしたら静的ファイルにアクセス出来ませんでした。

特定のパスだけOKにする

StaticFilesがファイルの種類を取得する場合にIContentTypeProviderを使っているのでIContentTypeProviderを実装して特定のパスだけOKにする方法。

public class LetsEncryptWellKnownContentTypeProvider : IContentTypeProvider
{
    private IContentTypeProvider _baseProvider;

    public LetsEncryptWellKnownContentTypeProvider()
        : this(new FileExtensionContentTypeProvider())
    { }

    public LetsEncryptWellKnownContentTypeProvider(IContentTypeProvider baseProvider)
    {
        _baseProvider = baseProvider;
    }

    public bool TryGetContentType(string subpath, out string contentType)
    {
        if (subpath.StartsWith("/.well-known/acme-challenge/"))
        {
            return true;
        }

        return _baseProvider.TryGetContentType(subpath, out contentType);
    }
}

で実装後は登録。

app.UseStaticFiles(new StaticFileOptions
{
    ContentTypeProvider = new LetsEncryptWellKnownContentTypeProvider()
});

ローカルは静的ファイルにアクセス出来たのに、App Serviceでは相変わらずだめでした。

Azure App ServiceではCore上の静的ファイルにアクセス出来ない!?

よくわかりませんが、あえてやる必要もないので諦めました。
stackoverflow.com

DNS認証が楽

certbot certonly --manual -d example.com --preferred-challenges dns

DNSが登録されたことを確認出来たら終了。