タグ: Solr

Solrのパッケージ管理機能

はじめに

Solr 8.4 からパッケージ管理機能が追加されました。リファレンスによると、ここでいうパッケージは1つまたは複数のプラグインを1つにまとめたものという意味のようです。
Solr におけるパッケージ管理について調べました。

パッケージ管理機能

従来、プラグインを利用するためには
・jar ファイルを特定の場所に置く
・solrconfig.xml の lib ディレクティブで jar ファイルの場所を指定する
という作業が必要でした。

SolrCloud環境では、複数のノードでこの作業を行う必要があります。 jar ファイルのアップデートの際に異なるノードでのバージョン違いが発生するリスクもあります。

パッケージ管理機能により、複数ノードへのプラグインのインストールやアップデートを一括で操作できるようになります。

パッケージ管理を有効にする

デフォルトではパッケージ管理機能は無効になっているので、起動時のオプションを指定して有効にします。

bin/solr -c -Denable.packages=true

リポジトリを追加する

パブリックなSolrパッケージリポジトリというものは存在していないようなので、Solr のソースに含まれていた、以下のサンプルプラグインをローカルのウェブサーバでホストして試してみました。

$ ls solr-8.4.1-src/solr/core/src/test-files/solr/question-answer-repository/
publickey.der  question-answer-request-handler-1.1.jar.tmp
question-answer-request-handler-1.0.jar.tmp  repository.json
$ cp solr-8.4.1-src/solr/core/src/test-files/solr/question-answer-repository/* $DOC_ROOT/solr/repo/

ウェブサーバ上の特定のディレクトリがパッケージリポジトリであるとSolrに認識されるためには repository.json ファイルが必要であるようです。

$ cat solr-8.4.1-src/solr/core/src/test-files/solr/question-answer-repository/repository.json
[
  {
    "name": "question-answer",
    "description": "A natural language question answering plugin",
    "versions": [
      {
        "version": "1.0.0",
        "date": "2019-01-01",
        "artifacts": [
          {
            "url": "question-answer-request-handler-1.0.jar.tmp",
            "sig": "TTzgh5/usbyWg7oZ7lRwz4eQfh1FeXWvv4U85tsVthVz0MRDz9t7SmonDkegZ7OyqeoiQ4I207pifpVW+DRd9Q=="
          }
        ],
        "manifest": {
          "version-constraint": "8 - 9",
          "plugins": [
            {
              "name": "request-handler",
              "setup-command": {
                "path": "/api/collections/${collection}/config",
                "payload": {"add-requesthandler": {"name": "${RH-HANDLER-PATH}", "class": "question-answer:fullstory.QA\
RequestHandler"}},
                "method": "POST"
              },
              "uninstall-command": {
                "path": "/api/collections/${collection}/config",
                "payload": {"delete-requesthandler": "${RH-HANDLER-PATH}"},
                "method": "POST"
              },
              "verify-command": {
                "path": "/api/collections/${collection}/config/requestHandler?componentName=${RH-HANDLER-PATH}&meta=tru\
e",
                "method": "GET",
                "condition": "$['config'].['requestHandler'].['${RH-HANDLER-PATH}'].['_packageinfo_'].['version']",
                "expected": "${package-version}"
              }
            }
          ],
          "parameter-defaults": {
            "RH-HANDLER-PATH": "/mypath"
          }
        }
      },
      {
        "version": "1.1.0",
        "date": "2019-01-01",
        "artifacts": [
          {
            "url": "question-answer-request-handler-1.1.jar.tmp",
            "sig": "LypqlmbJ76AWa5jx0XhjKxO4lrcQAvpSuYddfzcE6TnX0VDPFhrlQHSSX6cZLtvNbQ+74xUMKgsoX1IUnEnKYw=="
          }
        ]
      }
    ]
  }
]

同じパッケージのバージョン違いがrepository.json で定義されています。

Solr稼働中に以下のコマンドでリポジトリを追加します。

$ bin/solr package add-repo question-answer http://localhost/solr/repo/

利用できるパッケージのリスト

インストール対象となるパッケージのリストを表示します。

$ bin/solr package list-available
Available packages:
-----
question-answer                 A natural language question answering plugin
        Version: 1.0.0
        Version: 1.1.0

インストール

$ bin/solr package install question-answer:1.0.0
Posting manifest...
Posting artifacts...
Executing Package API to register this package...
Response: {"responseHeader":{
    "status":0,
    "QTime":42}}
question-answer installed.

インストール済みパッケージの確認

$ bin/solr package list-installed
Installed packages:
-----
{
  "name":"question-answer",
  "version":"1.0.0"}

デプロイ

コレクションを指定してデプロイします。

$ bin/solr package deploy question-answer -collections test
Executing {"add-requesthandler":{"name":"/mypath","class":"question-answer:fullstory.QARequestHandler"}} for path:/api/\
collections/test/config
Execute this command (y/n):
y
Executing http://localhost:8983/api/collections/test/config/requestHandler?componentName=/mypath&meta=true for collecti\
on:test
{
  "responseHeader":{
    "status":0,
    "QTime":0},
  "config":{"requestHandler":{"/mypath":{
        "name":"/mypath",
        "class":"question-answer:fullstory.QARequestHandler",
        "_packageinfo_":{
          "package":"question-answer",
          "version":"1.0.0",
          "files":["/package/question-answer/1.0.0/question-answer-request-handler-1.0.jar.tmp"],
          "manifest":"/package/question-answer/1.0.0/manifest.json",
          "manifestSHA512":"a91ab5a2c5abd53f0f72c256592c2be8b667cecb8226ac054aeed4d28aac9d743311442f2d58539bb83663a19bd\
1efb310aaadfd77bea458f3d475161721a114"}}}}}

Actual: 1.0.0, expected: 1.0.0
Deployed on [test] and verified package: question-answer, version: 1.0.0
Deployment successful

repository.json の記述にしたがって /mypath で QARequestHandler が動くように Config API が呼ばれたことが分かります。
/mypath をリクエストしてみます。

$ curl http://localhost:8983/solr/test/mypath
{
  "responseHeader":{
    "status":0,
    "QTime":0},
  "responseHeader":[
    "version","1.0"]}

残念ながら QARequestHandler のソースを見つけることができず、具体的にどんなパラメータでどんな機能が使えるのかが不明ですが、デプロイできていることは確認できました。

パッケージのアップデート

$ bin/solr package install question-answer:1.1.0
Posting manifest...
Posting artifacts...
Executing Package API to register this package...
Response: {"responseHeader":{
    "status":0,
    "QTime":4}}
question-answer installed.
$ bin/solr package list-installed
Installed packages:
-----
{
  "name":"question-answer",
  "version":"1.0.0"}
{
  "name":"question-answer",
  "version":"1.1.0"}

同じパッケージの2つのバージョンがインストールされたことが分かります。

新しい方のバージョンをデプロイします。

$ bin/solr package deploy question-answer:1.1.0 -collections test
Package {
  "name":"question-answer",
  "version":"1.0.0"} already deployed on test. To update to {
  "name":"question-answer",
  "version":"1.1.0"}, pass --update parameter.
Already Deployed on [test], package: question-answer, version: 1.1.0
Deployment failed

失敗しました。
リファレンスを確認すると、上書きデプロイのときは –update オプションが必要とのことです。

$ bin/solr package deploy question-answer:1.1.0 -collections test --update
Executing http://localhost:8983/api/collections/test/config/requestHandler?componentName=/mypath&meta=true for collecti\
on:test
{
  "responseHeader":{
    "status":0,
    "QTime":1},
  "config":{"requestHandler":{"/mypath":{
        "name":"/mypath",
        "class":"question-answer:fullstory.QARequestHandler",
        "_packageinfo_":{
          "package":"question-answer",
          "version":"1.1.0",
          "files":["/package/question-answer/1.1.0/question-answer-request-handler-1.1.jar.tmp"],
          "manifest":"/package/question-answer/1.1.0/manifest.json",
          "manifestSHA512":"be22126df3fbb84284cdb94469fa0f83753961c066451f0b9107312d076f3f016e60fd279951656ee7ff4b17bc2\
57fbd2ce8950533c7d394b1080122f6461606"}}}}}

Actual: 1.1.0, expected: 1.1.0
Deployed on [test] and verified package: question-answer, version: 1.1.0
Deployment successful

今度は成功しました。
/mypath にリクエストを投げて、バージョン1.1にアップデートされたことを確認します。

$ curl http://localhost:8983/solr/test/mypath
{
  "responseHeader":{
    "status":0,
    "QTime":0},
  "responseHeader":[
    "version","1.1"]}

デプロイ中のパッケージをリストするコマンドもあります。

$ bin/solr package list-deployed -c test
Packages deployed on test:
{
  "name":"question-answer",
  "version":"1.1.0"}

おわりに

Solrのパッケージ管理機能の使い方を見てきました。次回はリポジトリを設定して自分で作ったパッケージを扱えるようにしてみます。


【Solr】Date Mathの仕様をソースコードで確認する

Solr のリファレンスガイドでは Date Math においてどの時間単位がどういう表記で許されているかの仕様はあまり詳しくは説明されておらず、いくつかの具体例が挙げられているのみです。 例に挙がっていない時間の単位が使えるのかはどうかは試してみないと分かりません。

そこで Solr 8.4.1 のソースコードで仕様を確認してみました。

Date Math を扱うクラスを探して org.apache.solr.util.DateMathParser というクラスに行き当たりました。そのソースコードでは、扱える単位は以下のように定義されていました。

    Map units = new HashMap<>(13);
    units.put("YEAR",        ChronoUnit.YEARS);
    units.put("YEARS",       ChronoUnit.YEARS);
    units.put("MONTH",       ChronoUnit.MONTHS);
    units.put("MONTHS",      ChronoUnit.MONTHS);
    units.put("DAY",         ChronoUnit.DAYS);
    units.put("DAYS",        ChronoUnit.DAYS);
    units.put("DATE",        ChronoUnit.DAYS);
    units.put("HOUR",        ChronoUnit.HOURS);
    units.put("HOURS",       ChronoUnit.HOURS);
    units.put("MINUTE",      ChronoUnit.MINUTES);
    units.put("MINUTES",     ChronoUnit.MINUTES);
    units.put("SECOND",      ChronoUnit.SECONDS);
    units.put("SECONDS",     ChronoUnit.SECONDS);
    units.put("MILLI",       ChronoUnit.MILLIS);
    units.put("MILLIS",      ChronoUnit.MILLIS);
    units.put("MILLISECOND", ChronoUnit.MILLIS);
    units.put("MILLISECONDS",ChronoUnit.MILLIS);

まとめると以下のようになります。ミリ秒の異表記が妙に充実していますね。

  • 年 : YEAR,YEARS
  • 月 : MONTH,MONTHS
  • 日 : DAY,DAYS,DATE
  • 時 : HOUR,HOURS
  • 分 : MINUTE,MINUTES
  • 秒 : SECOND,SECONDS
  • ミリ秒 : MILLI,MILLIS,MILLISECOND,MILLISECONDS

週(WEEK)が見当たりませんが、近くに書かれているコメントによると、週については
/WEEK と書いたときの丸め処理(たとえば NOW/DAY と書くとその日の0時0分0秒になる)がややこしいので今のところ採用していないとのことです。


【Solr】Date Mathによる日付表現

はじめに

Solr では、pdate 等の時刻を扱うフィールドに対するクエリで使用できる Date Math という表現が用意されています。「今日からN日前」のような表現を使いたいときに便利です。 この記事ではDate Mathについてまとめました。

通常の日付表現

Solr では日付のフィールドは以下の形式で表現します。

2020-03-22T14:55:29Z

ミリ秒までの精度があるので、小数点表記も有効です。

2020-03-22T14:55:29.123Z

時刻は秒まできちんと表記しなければエラーになります。

ミリ秒よりも小さい桁が書いてあっても受付けますが、無視されます。

エラーになる例

2020-03-22
2020-03-22T14:55Z

Date Math

Date Mathは、特定の時点からの相対的な時刻を指定しやすくするための表記法です。
起点として良く使用される「今現在」を指定するために NOW という Date Math が用意されています。

Date Mathではまず起点となる日付を書き、それプラスN日という形で表記します。
「2ヶ月後」

NOW+2MONTH

「10日前」

NOW-10DAY

「1年後」

NOW-1YEAR

プラス/マイナスの部分は連続して書くことができます。

NOW+1YEAR+3MONTH+5DAY

起点として通常の日付を指定することもできます。

2020-03-22T10:15:18Z+7DAY

丸め表記

スラッシュ(‘/’)を併用することで、「〜の最初」を表現できます。
たとえば現在時刻が2020年3月22日11時22分33秒だとします。

NOW/HOUR

→2020年3月22日11時00分00秒

NOW/DAY

→2020年3月22日00時00分00秒

Date Math と組み合わせて使えるリクエストパラメータ

NOW

NOW パラメータにより、Date Math で記述した “NOW” を特定の日付に設定することができます。 NOW パラメータには、いわゆる UNIX TIME の Long 値を指定します。
NOW パラメータを指定することで、複数のノードにまたがる分散検索での NOW の値を揃えることができます。テストのときにも役に立ちそうです。

TZ

TZ パラメータを指定することで、デフォルト UTC である Date Math の日付計算を別のタイムゾーンとして扱うことができます。


SolrのDateRangeFieldで日時の範囲を扱う

はじめに

Solrで日時を扱うためのフィールドタイプとして、通常使う DatePointField の他にもう一つ DateRangeField があります。その名の通り幅の有る時間を取り扱えます。

DateRangeFieldとDatePointField

店舗の営業時間を扱うことを考えてみます。

<fieldType name="pdate" class="solr.DatePointField" docValues="true"/>
<field name="start" type="pdate" indexed="true"/>
<field name="end" type="pdate" indexed="true"/>

与えられた時刻(たとえば2020年3月1日19時)に営業している店舗を調べるには、営業開始時刻(start)と営業終了時刻(end)のフィールドを定義して、「startが2020年3月1日19時よりも前」かつ「endが2020年3月1日19時よりも後」である店舗を検索します。 (話を簡単にするためこの記事ではタイムゾーンのことは考えないことにします)

start:[* TO 2020-03-01T19:00:00Z] AND end:[2020-03-01T19:00:00Z * TO]

対して DateRangeFieldを使えば、営業時間のフィールドが1つで済みます

<fieldType name="rdate" class="solr.DateRangeField" docValues="true"/>
<field name="start_end" type="rdate" indexed="true" multiValued="true"/>

投入するデータは以下のような形式です。

[
    {
     "id":"1",
     "start_end":[
	 "[2020-03-01T18:00Z TO 2020-03-01T23:00Z]"
     ]
    }
]

以下のクエリで2020年3月1日19時に営業している店舗を検索できます。

start_end:"2020-03-01T19:00:00Z"

DateRangeFieldを使うパターンだと営業時間を複数登録するのも簡単です。

[
    {
     "id":"2",
     "start_end":[
	 "[2020-03-01T11:00Z TO 2020-03-01T14:00Z]",
	 "[2020-03-01T18:00Z TO 2020-03-01T23:00Z]",
	 "[2020-03-02T18:00Z TO 2020-03-02T23:00Z]",
	 "[2020-03-04T11:00Z TO 2020-03-04T14:00Z]",
	 "[2020-03-04T18:00Z TO 2020-03-04T23:00Z]"
     ]
    }
]

クエリは先程と同じもので大丈夫です。

start_end:"2020-03-01T19:00:00Z"

DatePointFieldでstartとendの2つのフィールドを使うパターンだと、どうでしょう?
start と end を multiValued にしても解決しません。

[
    {
     "id":"10",
     "start":["2020-03-01T11:00Z","2020-03-01T18:00Z"],
     "end":["2020-03-01T14:00Z","2020-03-01T23:00Z"]
    }
]

と登録したとして、startのどちらがendのどちらに対応しているのかが検索時に区別できないからです。したがって、別のレコードに分けなければなりません。

[
    {
     "id":"10",
     "start":"2020-03-01T11:00Z",
     "end":"2020-03-01T14:00Z"
    },
    {
     "id":"11",
     "start":"2020-03-01T18:00Z",
     "end":"2020-03-01T23:00Z"
    }
]

営業時間だけを扱っている分にはこれでも良さそうに見えますが、他の店舗情報(店舗名、住所、電話番号等)もインデックスに含めるとすると、以下のどちらかを考えなければならなくなります。

  • すべてのレコードに店舗情報を含める(すごく冗長)
  • 店舗情報と営業時間情報を分けてJOINする(処理が複雑になる)

どちらにしても、DateRangeField を使った場合のシンプルさには比べるべくもありません。

検索時のオプション

インデックス側とクエリ側のどちらも時間範囲である場合、以下の5通りの組み合わせが考えられます。

  1. 全く重ならない(例: インデックス「1時から2時」クエリ「4時から5時」)
  2. 完全に一致する(例: インデックス「1時から2時」クエリ「4時から5時」)
  3. 一部分が重なる(例: インデックス「1時から2時」クエリ「1時半から3時」)
  4. インデックス側がクエリ側に含まれる(例: インデックス「1時から2時」クエリ「0時から3時」)
  5. クエリ側がインデックス側に含まれる(例: インデックス「1時から2時」クエリ「1時20分から1時40分」)

検索クエリとしてヒットしたかどうかの判定時に、1はヒットしない、2はヒットしたでいいのですが、3,4,5は要件によって判定を変えたいことがあります。そこで、以下のオプションが用意されています。

  • Intersects(デフォルト): 2,3,4,5がヒット
  • Within: 2,4がヒット
  • Contains: 2,5がヒット

と思ったら、8.4.0の実際の挙動は以下の通りでした。

  • Intersects(デフォルト): 2,3,4,5がヒット
  • Within: 4がヒット
  • Contains: 2,5がヒット

具体的には

[2020-03-01T01:00Z TO 2020-03-01T02:00Z]

というデータに対して

{!field f=dateRange op=Within}[2020-03-01T01:00:00Z TO 2020-03-01T02:00:00Z]

というクエリがヒットしませんでした。opがContainsやIntersectsならヒットしました。Withinの場合は両端のどちらかが一致しているとヒットにはならず、インデックス側が完全に内側に無いといけないようです。

おわりに

DateRangeFieldを使うと、幅の有る時間のデータをシンプルに取り扱うことができます。「日付データ→pdate」と短絡せず、要件に合わせて使い分けるようにしたいところです。


Solr 8.4.0 で追加された”Untrusted Configsets”の制限について

Solr 8.4.0 の Changes には以下の項目があります。

SOLR-14071: Untrusted configsets (ones that are uploaded via unsecured configset API) cannot use <lib> directive. Consider enabling authentication/authorization so that the uploaded configsets are trusted. Note: If you already have a collection using untrusted configset that uses directive, it will not load after upgrading to 8.4. You can re-upload your configset using “bin/solr zk -upconfig ..” or place your libraries in the classpath and restart Solr.

「Untrusted configsets は lib ディレクティブを使えません」とあります。
configsets が trusted として扱われるためには、認証有りでアップロードしなければならないとのことです。Solr 8.4.0 では _default の solrconfig.xml から lib を使う設定が無くなったのもこの変更に合わせてのようです。

Untrusted configsets では lib ディレクティブが使えないというのが具体的にどういう意味なのかを確認してみました。

まず Solr 8.4.0 が起動した状態で sample_techproducts_configs (このサンプル設定には 8.4.0 でも lib ディレクティブが含まれます)を configsets_test という名前でアップロードします。

$ (cd solr-8.4.0/server/solr/configsets/sample_techproducts_configs/conf && zip -r - *) > configsets_test.zip
$ curl -X POST --header "Content-Type:application/octet-stream" --data-binary @configsets_test.zip "http://localhost:8983/solr/admin/configs?action=UPLOAD&name=configsets_test"

アップロードした configsets_test を使ってコレクションを作成します。

curl -s "http://localhost:8983/solr/admin/collections?action=CREATE&name=configsets_test&numShards=1&replicationFactor=1&collection.configName=configsets_test&omitHeader=true"
{
  "failure":{
    "127.0.1.1:8983_solr":"org.apache.solr.client.solrj.impl.HttpSolrClient$RemoteSolrException:Error from server at http://127.0.1.1:8983/solr: Error CREATEing SolrCore 'configsets_test_shard1_replica_n1': Unable to create core [configsets_test_shard1_replica_n1] Caused by: The configset for this collection was uploaded without any authentication in place, and use of  is not available for collections with untrusted configsets. To use this component, re-upload the configset after enabling authentication and authorization."},
  "Operation create caused exception:":"org.apache.solr.common.SolrException:org.apache.solr.common.SolrException: Underlying core creation failed while creating collection: configsets_test",
  "exception":{
    "msg":"Underlying core creation failed while creating collection: configsets_test",
    "rspCode":400},
  "error":{
    "metadata":[
      "error-class","org.apache.solr.common.SolrException",
      "root-error-class","org.apache.solr.common.SolrException"],
    "msg":"Underlying core creation failed while creating collection: configsets_test",
    "code":400}}

アップロードはできましたが、その configsets を使ってコレクションを作成することろでエラーになりました。

次に BASIC 認証を設定してからコレクション作成してみます。

$ ./solr-8.4.0/server/scripts/cloud-scripts/zkcli.sh -zkhost localhost:9983 -cmd put /security.json '{
"authentication":{
   "blockUnknown": true,
   "class":"solr.BasicAuthPlugin",
   "credentials":{"solr":"IV0EHq1OnNrj6gvRCwvFwTrZ1+z1oBbnQdiVC3otuq0= Ndd7LKvVBAaZIF0QAVi1ekCfAJXr1GGfLtRUXhgrF8c="}
 }
}'

ここで Solr を再起動して BASIC 認証が有効になった状態で再度コレクション作成。

$ curl --user solr:SolrRocks -s "http://localhost:8983/solr/admin/collections?action=CREATE&name=configsets_test&numShards=1&replicationFactor=1&collection.configName=configsets_test&omitHeader=true"
{
  "failure":{
    "127.0.1.1:8983_solr":"org.apache.solr.client.solrj.impl.HttpSolrClient$RemoteSolrException:Error from server at http://127.0.1.1:8983/solr: Error CREATEing SolrCore 'configsets_test_shard1_replica_n1': Unable to create core [configsets_test_shard1_replica_n1] Caused by: The configset for this collection was uploaded without any authentication in place, and use of  is not available for collections with untrusted configsets. To use this component, re-upload the configset after enabling authentication and authorization."},
  "Operation create caused exception:":"org.apache.solr.common.SolrException:org.apache.solr.common.SolrException: Underlying core creation failed while creating collection: configsets_test",
  "exception":{
    "msg":"Underlying core creation failed while creating collection: configsets_test",
    "rspCode":400},
  "error":{
    "metadata":[
      "error-class","org.apache.solr.common.SolrException",
      "root-error-class","org.apache.solr.common.SolrException"],
    "msg":"Underlying core creation failed while creating collection: configsets_test",
    "code":400}}

やはりエラーになります。

confitsets を trusted として扱ってもらうために、認証有りの状態で再度アップロードします。UPLOAD コマンドでは上書きできないので、DELETE してから UPLOAD します。

$ curl --user solr:SolrRocks -X POST --header "Content-Type:application/octet-stream" --data-binary @configsets_test.zip "http://localhost:8983/solr/admin/configs?action=DELETE&name=configsets_test"
{
  "responseHeader":{
    "status":0,
    "QTime":220}}
$ curl --user solr:SolrRocks -X POST --header "Content-Type:application/octet-stream" --data-binary @configsets_test.zip "http://localhost:8983/solr/admin/configs?action=UPLOAD&name=configsets_test"
{
  "responseHeader":{
    "status":0,
    "QTime":292}}

認証有りでアップロードした configsets を使ってコレクションを作成してみます。

$ curl --user solr:SolrRocks -s "http://localhost:8983/solr/admin/collections?action=CREATE&name=configsets_test&numShards=1&replicationFactor=1&collection.configName=configsets_test&omitHeader=true"
{
  "success":{
    "127.0.1.1:8983_solr":{
      "responseHeader":{
        "status":0,
        "QTime":2126},
      "core":"configsets_test_shard1_replica_n1"}}}

今度はうまくいきました。

結論としては、「Untrusted configsets では lib ディレクティブが使えない」とは、libディレクティブを含む Untrusted configsets ではコレクションを生成できないという意味でした。

ところで、configsets アップロードする方法としては、Solr の Configsets API を使う方法とは別に zookeeper に直接アップロードする方法もあります。

$ ./solr-8.4.0/server/scripts/cloud-scripts/zkcli.sh -zkhost localhost:9983 -cmd upconfig -confdir solr-8.4.0/server/solr/configsets/sample_techproducts_configs/conf -confname configsets_test2
INFO  - 2020-02-23 22:52:50.804; org.apache.solr.common.cloud.ConnectionManager; Waiting for client to connect to ZooKeeper
INFO  - 2020-02-23 22:52:50.821; org.apache.solr.common.cloud.ConnectionManager; zkClient has connected
INFO  - 2020-02-23 22:52:50.821; org.apache.solr.common.cloud.ConnectionManager; Client is connected to ZooKeeper
$ curl --user solr:SolrRocks -s "http://localhost:8983/solr/admin/collections?action=CREATE&name=configsets_test2&numShards=1&replicationFactor=1&collection.configName=configsets_test2&omitHeader=true"
{
  "success":{
    "127.0.1.1:8983_solr":{
      "responseHeader":{
        "status":0,
        "QTime":1361},
      "core":"configsets_test2_shard1_replica_n1"}}}

なんとコレクション生成できてしまいました。

現時点では Untrusted Configsets の制限はまだ不十分なようで、今後の進展に注意する必要がありそうです。