Skip to content

Commit 0994c0a

Browse files
committed
Fix entitlement policy, including test
1 parent 1459ea9 commit 0994c0a

File tree

3 files changed

+148
-6
lines changed

3 files changed

+148
-6
lines changed

build.gradle

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,16 @@ dependencies {
5757

5858
def embedVersion = tasks.register('embedVersion', Copy) {
5959
var esKind = sudachiEs.kind.get()
60-
from 'src/main/extras/plugin-descriptor.properties'
60+
from('src/main/extras/plugin-descriptor.properties') {
61+
expand([
62+
version: version,
63+
engineVersion: esKind.version,
64+
engineKind: esKind.engine.kind
65+
])
66+
}
67+
// Include entitlement policy for Elasticsearch 9+
68+
from('src/main/extras/entitlement-policy.yaml')
6169
into "build/package/${version}/${esKind.engine.kind}-${esKind.version}"
62-
expand([
63-
version: version,
64-
engineVersion: esKind.version,
65-
engineKind: esKind.engine.kind
66-
])
6770
inputs.property("version", version)
6871
inputs.property("elasticSearchVersion", esKind.version)
6972
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* Copyright (c) 2025 Works Applications Co., Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.worksap.nlp.elasticsearch.sudachi
18+
19+
import kotlin.io.path.exists
20+
import kotlin.test.Test
21+
import org.junit.Assert
22+
23+
/**
24+
* Integration test to verify that the entitlement policy grants proper permissions for the plugin
25+
* to operate in Elasticsearch 9+.
26+
*
27+
* This test verifies:
28+
* 1. Plugin and dictionary files are accessible
29+
* 2. Default config can be read from plugin JAR (requires file read entitlement)
30+
* 3. Tokenizer works end-to-end without NotEntitledException
31+
* 4. Entitlement policy file is valid and parseable
32+
*/
33+
class EntitlementTest : SudachiEnvTest() {
34+
35+
@Test
36+
fun pluginAndDictionaryFilesAccessible() {
37+
// Verify plugin directory structure and dictionary files are accessible
38+
// This requires entitlement policy to grant read access to both plugin and config directories
39+
val pluginDir = sudachiEnv.pluginsPath.resolve("analysis-sudachi")
40+
Assert.assertTrue("Plugin directory should exist: $pluginDir", pluginDir.exists())
41+
42+
// Check SPI directory if it exists
43+
val spiDir = pluginDir.resolve("spi")
44+
if (spiDir.exists()) {
45+
Assert.assertTrue("SPI directory should be readable: $spiDir", spiDir.toFile().canRead())
46+
}
47+
48+
// Verify dictionary files in config/sudachi directory
49+
val sudachiConfigDir = sudachiEnv.configPath.resolve("sudachi")
50+
Assert.assertTrue("Config directory should exist: $sudachiConfigDir", sudachiConfigDir.exists())
51+
52+
val systemDict = sudachiConfigDir.resolve("system_core.dic")
53+
Assert.assertTrue("System dictionary should exist: $systemDict", systemDict.exists())
54+
}
55+
56+
@Test
57+
fun tokenizerWorksWithDefaultConfig() {
58+
// End-to-end test: Create tokenizer without settings_path (forces default config from JAR)
59+
// This exercises the full entitlement chain:
60+
// 1. Plugin loads without NotEntitledException
61+
// 2. Read default config from plugin JAR
62+
// 3. Read dictionary from config directory
63+
// 4. Initialize and use tokenizer
64+
65+
val req = AnalyzeActionRequestAlias("sudachi_test")
66+
req.tokenizer(
67+
mapOf(
68+
"type" to "sudachi_tokenizer",
69+
// No settings_path - forces Config.defaultConfig() call from JAR
70+
"split_mode" to "C"))
71+
req.text("東京都")
72+
73+
val analyzers = analysisRegistry()
74+
75+
// If entitlement is missing, this would throw NotEntitledException
76+
val response =
77+
TransportAnalyzeActionAlias.analyze(
78+
req,
79+
analyzers,
80+
null,
81+
1000,
82+
)
83+
84+
// Verify tokenization works correctly
85+
Assert.assertTrue("Should tokenize successfully", response.tokens.isNotEmpty())
86+
Assert.assertEquals("東京都", response.tokens[0].term)
87+
}
88+
89+
@Test
90+
fun entitlementPolicyIsValidAndParseable() {
91+
// This test validates that:
92+
// 1. The entitlement-policy.yaml file is packaged with the plugin
93+
// 2. The policy would be accepted during real plugin installation
94+
// It uses Elasticsearch's actual policy parser to ensure the syntax is correct
95+
val pluginDir = sudachiEnv.pluginsPath.resolve("analysis-sudachi")
96+
val entitlementPolicyFile = pluginDir.resolve("entitlement-policy.yaml")
97+
98+
Assert.assertTrue(
99+
"entitlement-policy.yaml must exist in plugin package: $entitlementPolicyFile",
100+
entitlementPolicyFile.exists())
101+
102+
try {
103+
// Use Elasticsearch's PolicyUtils to parse the policy file
104+
// This is the same parser used during plugin installation
105+
val policy =
106+
org.elasticsearch.entitlement.runtime.policy.PolicyUtils.parsePolicyIfExists(
107+
"analysis-sudachi", entitlementPolicyFile, true)
108+
109+
// If we get here without an exception, the policy file is valid!
110+
Assert.assertNotNull(
111+
"Policy should be parsed successfully - this means the YAML syntax is correct and would be accepted during real plugin installation",
112+
policy)
113+
114+
println("SUCCESS: entitlement-policy.yaml parsed successfully by Elasticsearch!")
115+
println("Policy name: ${policy.name}")
116+
} catch (e: org.elasticsearch.entitlement.runtime.policy.PolicyParserException) {
117+
Assert.fail(
118+
"entitlement-policy.yaml has invalid syntax and would fail during plugin installation: ${e.message}")
119+
} catch (e: Exception) {
120+
Assert.fail(
121+
"Unexpected error while parsing entitlement-policy.yaml: ${e.javaClass.simpleName}: ${e.message}")
122+
}
123+
}
124+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Entitlement policy for analysis-sudachi plugin
2+
# This file declares the permissions required by the plugin to operate
3+
# See: https://www.elastic.co/guide/en/elasticsearch/plugins/current/_entitlements.html
4+
5+
# Grant file read access for the plugin and its dependencies
6+
ALL-UNNAMED:
7+
- files:
8+
# Allow reading from the plugin's own directory (including spi subdirectory)
9+
- relative_path: plugins/analysis-sudachi
10+
relative_to: home
11+
mode: read
12+
# Allow reading from the config directory for dictionaries
13+
- relative_path: sudachi
14+
relative_to: config
15+
mode: read

0 commit comments

Comments
 (0)