diff --git a/docs/changelog/122938.yaml b/docs/changelog/122938.yaml new file mode 100644 index 0000000000000..cfb6e319c6cd2 --- /dev/null +++ b/docs/changelog/122938.yaml @@ -0,0 +1,5 @@ +pr: 122938 +summary: Fix geoip databases index access after system feature migration (again) +area: Ingest Node +type: bug +issues: [] diff --git a/docs/changelog/123155.yaml b/docs/changelog/123155.yaml new file mode 100644 index 0000000000000..73027c87510ba --- /dev/null +++ b/docs/changelog/123155.yaml @@ -0,0 +1,5 @@ +pr: 123155 +summary: Add `ElasticInferenceServiceCompletionServiceSettings` +area: Machine Learning +type: bug +issues: [] diff --git a/libs/entitlement/bridge/src/main/java/module-info.java b/libs/entitlement/bridge/src/main/java/module-info.java index 518a0a1ef29ec..6a85013c1f1f5 100644 --- a/libs/entitlement/bridge/src/main/java/module-info.java +++ b/libs/entitlement/bridge/src/main/java/module-info.java @@ -12,6 +12,7 @@ module org.elasticsearch.entitlement.bridge { requires java.net.http; requires jdk.net; + requires java.logging; exports org.elasticsearch.entitlement.bridge; } diff --git a/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/EntitlementChecker.java b/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/EntitlementChecker.java index e4bb493236dc7..63781822ae4ff 100644 --- a/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/EntitlementChecker.java +++ b/libs/entitlement/bridge/src/main/java/org/elasticsearch/entitlement/bridge/EntitlementChecker.java @@ -80,6 +80,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.ForkJoinPool; import java.util.function.BiPredicate; +import java.util.logging.FileHandler; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; @@ -820,9 +821,34 @@ public interface EntitlementChecker { void check$java_nio_file_Files$$lines(Class callerClass, Path path); - // file system providers void check$java_nio_file_spi_FileSystemProvider$(Class callerClass); + void check$java_util_logging_FileHandler$(Class callerClass); + + void check$java_util_logging_FileHandler$(Class callerClass, String pattern); + + void check$java_util_logging_FileHandler$(Class callerClass, String pattern, boolean append); + + void check$java_util_logging_FileHandler$(Class callerClass, String pattern, int limit, int count); + + void check$java_util_logging_FileHandler$(Class callerClass, String pattern, int limit, int count, boolean append); + + void check$java_util_logging_FileHandler$(Class callerClass, String pattern, long limit, int count, boolean append); + + void check$java_util_logging_FileHandler$close(Class callerClass, FileHandler that); + + void check$java_net_http_HttpRequest$BodyPublishers$$ofFile(Class callerClass, Path path); + + void check$java_net_http_HttpResponse$BodyHandlers$$ofFile(Class callerClass, Path path); + + void check$java_net_http_HttpResponse$BodyHandlers$$ofFile(Class callerClass, Path path, OpenOption... options); + + void check$java_net_http_HttpResponse$BodyHandlers$$ofFileDownload(Class callerClass, Path directory, OpenOption... openOptions); + + void check$java_net_http_HttpResponse$BodySubscribers$$ofFile(Class callerClass, Path directory); + + void check$java_net_http_HttpResponse$BodySubscribers$$ofFile(Class callerClass, Path directory, OpenOption... openOptions); + void checkNewFileSystem(Class callerClass, FileSystemProvider that, URI uri, Map env); void checkNewFileSystem(Class callerClass, FileSystemProvider that, Path path, Map env); diff --git a/libs/entitlement/qa/entitled-plugin/src/main/java/module-info.java b/libs/entitlement/qa/entitled-plugin/src/main/java/module-info.java index eafac9006daec..74559a12a4da4 100644 --- a/libs/entitlement/qa/entitled-plugin/src/main/java/module-info.java +++ b/libs/entitlement/qa/entitled-plugin/src/main/java/module-info.java @@ -12,6 +12,7 @@ requires org.elasticsearch.entitlement; requires org.elasticsearch.base; // SuppressForbidden requires org.elasticsearch.logging; + requires java.logging; exports org.elasticsearch.entitlement.qa.entitled; // Must be unqualified so non-modular IT tests can call us } diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/DummyImplementations.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/DummyImplementations.java index 929ec4ce731d3..6529d63147272 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/DummyImplementations.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/DummyImplementations.java @@ -13,7 +13,6 @@ import org.elasticsearch.core.SuppressForbidden; -import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.DatagramPacket; @@ -459,71 +458,71 @@ public Socket createSocket(Socket s, String host, int port, boolean autoClose) { } static class DummyDatagramSocket extends DatagramSocket { - DummyDatagramSocket() throws SocketException { + DummyDatagramSocket() { super(new DatagramSocketImpl() { @Override - protected void create() throws SocketException {} + protected void create() {} @Override - protected void bind(int lport, InetAddress laddr) throws SocketException {} + protected void bind(int lport, InetAddress laddr) {} @Override - protected void send(DatagramPacket p) throws IOException {} + protected void send(DatagramPacket p) {} @Override - protected int peek(InetAddress i) throws IOException { + protected int peek(InetAddress i) { return 0; } @Override - protected int peekData(DatagramPacket p) throws IOException { + protected int peekData(DatagramPacket p) { return 0; } @Override - protected void receive(DatagramPacket p) throws IOException {} + protected void receive(DatagramPacket p) {} @Override - protected void setTTL(byte ttl) throws IOException {} + protected void setTTL(byte ttl) {} @Override - protected byte getTTL() throws IOException { + protected byte getTTL() { return 0; } @Override - protected void setTimeToLive(int ttl) throws IOException {} + protected void setTimeToLive(int ttl) {} @Override - protected int getTimeToLive() throws IOException { + protected int getTimeToLive() { return 0; } @Override - protected void join(InetAddress inetaddr) throws IOException {} + protected void join(InetAddress inetaddr) {} @Override - protected void leave(InetAddress inetaddr) throws IOException {} + protected void leave(InetAddress inetaddr) {} @Override - protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) throws IOException {} + protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) {} @Override - protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) throws IOException {} + protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) {} @Override protected void close() {} @Override - public void setOption(int optID, Object value) throws SocketException {} + public void setOption(int optID, Object value) {} @Override - public Object getOption(int optID) throws SocketException { + public Object getOption(int optID) { return null; } @Override - protected void connect(InetAddress address, int port) throws SocketException {} + protected void connect(InetAddress address, int port) {} }); } } @@ -534,54 +533,54 @@ private static RuntimeException unexpected() { static class DummySelectorProvider extends SelectorProvider { @Override - public DatagramChannel openDatagramChannel() throws IOException { + public DatagramChannel openDatagramChannel() { return null; } @Override - public DatagramChannel openDatagramChannel(ProtocolFamily family) throws IOException { + public DatagramChannel openDatagramChannel(ProtocolFamily family) { return null; } @Override - public Pipe openPipe() throws IOException { + public Pipe openPipe() { return null; } @Override - public AbstractSelector openSelector() throws IOException { + public AbstractSelector openSelector() { return null; } @Override - public ServerSocketChannel openServerSocketChannel() throws IOException { + public ServerSocketChannel openServerSocketChannel() { return null; } @Override - public SocketChannel openSocketChannel() throws IOException { + public SocketChannel openSocketChannel() { return null; } } static class DummyAsynchronousChannelProvider extends AsynchronousChannelProvider { @Override - public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory threadFactory) throws IOException { + public AsynchronousChannelGroup openAsynchronousChannelGroup(int nThreads, ThreadFactory threadFactory) { return null; } @Override - public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize) throws IOException { + public AsynchronousChannelGroup openAsynchronousChannelGroup(ExecutorService executor, int initialSize) { return null; } @Override - public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group) throws IOException { + public AsynchronousServerSocketChannel openAsynchronousServerSocketChannel(AsynchronousChannelGroup group) { return null; } @Override - public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group) throws IOException { + public AsynchronousSocketChannel openAsynchronousSocketChannel(AsynchronousChannelGroup group) { return null; } } @@ -605,7 +604,7 @@ public String getScheme() { } @Override - public FileSystem newFileSystem(URI uri, Map env) throws IOException { + public FileSystem newFileSystem(URI uri, Map env) { return null; } @@ -620,53 +619,52 @@ public Path getPath(URI uri) { } @Override - public SeekableByteChannel newByteChannel(Path path, Set options, FileAttribute... attrs) - throws IOException { + public SeekableByteChannel newByteChannel(Path path, Set options, FileAttribute... attrs) { return null; } @Override - public DirectoryStream newDirectoryStream(Path dir, DirectoryStream.Filter filter) throws IOException { + public DirectoryStream newDirectoryStream(Path dir, DirectoryStream.Filter filter) { return null; } @Override - public void createDirectory(Path dir, FileAttribute... attrs) throws IOException { + public void createDirectory(Path dir, FileAttribute... attrs) { } @Override - public void delete(Path path) throws IOException { + public void delete(Path path) { } @Override - public void copy(Path source, Path target, CopyOption... options) throws IOException { + public void copy(Path source, Path target, CopyOption... options) { } @Override - public void move(Path source, Path target, CopyOption... options) throws IOException { + public void move(Path source, Path target, CopyOption... options) { } @Override - public boolean isSameFile(Path path, Path path2) throws IOException { + public boolean isSameFile(Path path, Path path2) { return false; } @Override - public boolean isHidden(Path path) throws IOException { + public boolean isHidden(Path path) { return false; } @Override - public FileStore getFileStore(Path path) throws IOException { + public FileStore getFileStore(Path path) { return null; } @Override - public void checkAccess(Path path, AccessMode... modes) throws IOException { + public void checkAccess(Path path, AccessMode... modes) { } @@ -676,104 +674,104 @@ public V getFileAttributeView(Path path, Class } @Override - public A readAttributes(Path path, Class type, LinkOption... options) throws IOException { + public A readAttributes(Path path, Class type, LinkOption... options) { return null; } @Override - public Map readAttributes(Path path, String attributes, LinkOption... options) throws IOException { + public Map readAttributes(Path path, String attributes, LinkOption... options) { return Map.of(); } @Override - public void setAttribute(Path path, String attribute, Object value, LinkOption... options) throws IOException { + public void setAttribute(Path path, String attribute, Object value, LinkOption... options) { } } static class DummyFileChannel extends FileChannel { @Override - protected void implCloseChannel() throws IOException { + protected void implCloseChannel() { } @Override - public int read(ByteBuffer dst) throws IOException { + public int read(ByteBuffer dst) { return 0; } @Override - public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { + public long read(ByteBuffer[] dsts, int offset, int length) { return 0; } @Override - public int write(ByteBuffer src) throws IOException { + public int write(ByteBuffer src) { return 0; } @Override - public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { + public long write(ByteBuffer[] srcs, int offset, int length) { return 0; } @Override - public long position() throws IOException { + public long position() { return 0; } @Override - public FileChannel position(long newPosition) throws IOException { + public FileChannel position(long newPosition) { return null; } @Override - public long size() throws IOException { + public long size() { return 0; } @Override - public FileChannel truncate(long size) throws IOException { + public FileChannel truncate(long size) { return null; } @Override - public void force(boolean metaData) throws IOException { + public void force(boolean metaData) { } @Override - public long transferTo(long position, long count, WritableByteChannel target) throws IOException { + public long transferTo(long position, long count, WritableByteChannel target) { return 0; } @Override - public long transferFrom(ReadableByteChannel src, long position, long count) throws IOException { + public long transferFrom(ReadableByteChannel src, long position, long count) { return 0; } @Override - public int read(ByteBuffer dst, long position) throws IOException { + public int read(ByteBuffer dst, long position) { return 0; } @Override - public int write(ByteBuffer src, long position) throws IOException { + public int write(ByteBuffer src, long position) { return 0; } @Override - public MappedByteBuffer map(MapMode mode, long position, long size) throws IOException { + public MappedByteBuffer map(MapMode mode, long position, long size) { return null; } @Override - public FileLock lock(long position, long size, boolean shared) throws IOException { + public FileLock lock(long position, long size, boolean shared) { return null; } @Override - public FileLock tryLock(long position, long size, boolean shared) throws IOException { + public FileLock tryLock(long position, long size, boolean shared) { return null; } } @@ -785,22 +783,22 @@ public boolean isOpen() { } @Override - public void close() throws IOException { + public void close() { } @Override - public long size() throws IOException { + public long size() { return 0; } @Override - public AsynchronousFileChannel truncate(long size) throws IOException { + public AsynchronousFileChannel truncate(long size) { return null; } @Override - public void force(boolean metaData) throws IOException { + public void force(boolean metaData) { } @@ -815,7 +813,7 @@ public Future lock(long position, long size, boolean shared) { } @Override - public FileLock tryLock(long position, long size, boolean shared) throws IOException { + public FileLock tryLock(long position, long size, boolean shared) { return null; } @@ -843,9 +841,9 @@ public Future write(ByteBuffer src, long position) { @SuppressForbidden(reason = "specifically testing readWriteSelectableChannel") static class DummySelectableChannelCloser implements Channels.SelectableChannelCloser { @Override - public void implCloseChannel(SelectableChannel sc) throws IOException {} + public void implCloseChannel(SelectableChannel sc) {} @Override - public void implReleaseChannel(SelectableChannel sc) throws IOException {} + public void implReleaseChannel(SelectableChannel sc) {} } } diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/FileCheckActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/FileCheckActions.java index aa0fdc33a36ec..b22643c90064e 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/FileCheckActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/FileCheckActions.java @@ -22,6 +22,8 @@ import java.io.FileWriter; import java.io.IOException; import java.io.RandomAccessFile; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; @@ -29,10 +31,13 @@ import java.security.KeyStore; import java.util.Scanner; import java.util.jar.JarFile; +import java.util.logging.FileHandler; import java.util.zip.ZipException; import java.util.zip.ZipFile; import static java.nio.charset.Charset.defaultCharset; +import static java.nio.file.StandardOpenOption.CREATE; +import static java.nio.file.StandardOpenOption.WRITE; import static java.util.zip.ZipFile.OPEN_DELETE; import static java.util.zip.ZipFile.OPEN_READ; import static org.elasticsearch.entitlement.qa.entitled.EntitledActions.createTempFileForWrite; @@ -40,7 +45,7 @@ import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS; @SuppressForbidden(reason = "Explicitly checking APIs that are forbidden") -@SuppressWarnings("unused") // Called via reflection +@SuppressWarnings({ "unused" /* called via reflection */, "ResultOfMethodCallIgnored" }) class FileCheckActions { static Path testRootDir = Paths.get(System.getProperty("es.entitlements.testdir")); @@ -62,17 +67,17 @@ static Path readWriteFile() { } @EntitlementTest(expectedAccess = PLUGINS) - static void fileCanExecute() throws IOException { + static void fileCanExecute() { readFile().toFile().canExecute(); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileCanRead() throws IOException { + static void fileCanRead() { readFile().toFile().canRead(); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileCanWrite() throws IOException { + static void fileCanWrite() { readFile().toFile().canWrite(); } @@ -101,68 +106,68 @@ static void fileDeleteOnExit() throws IOException { } @EntitlementTest(expectedAccess = PLUGINS) - static void fileExists() throws IOException { + static void fileExists() { readFile().toFile().exists(); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileIsDirectory() throws IOException { + static void fileIsDirectory() { readFile().toFile().isDirectory(); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileIsFile() throws IOException { + static void fileIsFile() { readFile().toFile().isFile(); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileIsHidden() throws IOException { + static void fileIsHidden() { readFile().toFile().isHidden(); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileLastModified() throws IOException { + static void fileLastModified() { readFile().toFile().lastModified(); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileLength() throws IOException { + static void fileLength() { readFile().toFile().length(); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileList() throws IOException { + static void fileList() { readDir().toFile().list(); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileListWithFilter() throws IOException { + static void fileListWithFilter() { readDir().toFile().list((dir, name) -> true); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileListFiles() throws IOException { + static void fileListFiles() { readDir().toFile().listFiles(); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileListFilesWithFileFilter() throws IOException { + static void fileListFilesWithFileFilter() { readDir().toFile().listFiles(pathname -> true); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileListFilesWithFilenameFilter() throws IOException { + static void fileListFilesWithFilenameFilter() { readDir().toFile().listFiles((dir, name) -> true); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileMkdir() throws IOException { + static void fileMkdir() { Path mkdir = readWriteDir().resolve("mkdir"); mkdir.toFile().mkdir(); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileMkdirs() throws IOException { + static void fileMkdirs() { Path mkdir = readWriteDir().resolve("mkdirs"); mkdir.toFile().mkdirs(); } @@ -175,27 +180,27 @@ static void fileRenameTo() throws IOException { } @EntitlementTest(expectedAccess = PLUGINS) - static void fileSetExecutable() throws IOException { + static void fileSetExecutable() { readWriteFile().toFile().setExecutable(false); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileSetExecutableOwner() throws IOException { + static void fileSetExecutableOwner() { readWriteFile().toFile().setExecutable(false, false); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileSetLastModified() throws IOException { + static void fileSetLastModified() { readWriteFile().toFile().setLastModified(System.currentTimeMillis()); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileSetReadable() throws IOException { + static void fileSetReadable() { readWriteFile().toFile().setReadable(true); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileSetReadableOwner() throws IOException { + static void fileSetReadableOwner() { readWriteFile().toFile().setReadable(true, false); } @@ -207,12 +212,12 @@ static void fileSetReadOnly() throws IOException { } @EntitlementTest(expectedAccess = PLUGINS) - static void fileSetWritable() throws IOException { + static void fileSetWritable() { readWriteFile().toFile().setWritable(true); } @EntitlementTest(expectedAccess = PLUGINS) - static void fileSetWritableOwner() throws IOException { + static void fileSetWritableOwner() { readWriteFile().toFile().setWritable(true, false); } @@ -363,6 +368,7 @@ static void keystoreGetInstance_FileLoadStoreParameter() throws IOException { } @EntitlementTest(expectedAccess = PLUGINS) + @SuppressWarnings("DataFlowIssue") // Passing null to a @NotNull parameter static void keystoreBuilderNewInstance() { try { KeyStore.Builder.newInstance("", null, readFile().toFile(), null); @@ -476,5 +482,86 @@ static void createScannerFileWithCharsetName() throws FileNotFoundException { new Scanner(readFile().toFile(), "UTF-8"); } + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void fileHandler() throws IOException { + new FileHandler(); + } + + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void fileHandler_String() throws IOException { + new FileHandler(readFile().toString()); + } + + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void fileHandler_StringBoolean() throws IOException { + new FileHandler(readFile().toString(), false); + } + + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void fileHandler_StringIntInt() throws IOException { + new FileHandler(readFile().toString(), 1, 2); + } + + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void fileHandler_StringIntIntBoolean() throws IOException { + new FileHandler(readFile().toString(), 1, 2, false); + } + + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void fileHandler_StringLongIntBoolean() throws IOException { + new FileHandler(readFile().toString(), 1L, 2, false); + } + + @EntitlementTest(expectedAccess = PLUGINS) + static void httpRequestBodyPublishersOfFile() throws IOException { + HttpRequest.BodyPublishers.ofFile(readFile()); + } + + @EntitlementTest(expectedAccess = PLUGINS) + static void httpResponseBodyHandlersOfFile() { + HttpResponse.BodyHandlers.ofFile(readWriteFile()); + } + + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void httpResponseBodyHandlersOfFile_readOnly() { + HttpResponse.BodyHandlers.ofFile(readFile()); + } + + @EntitlementTest(expectedAccess = PLUGINS) + static void httpResponseBodyHandlersOfFileDownload() { + HttpResponse.BodyHandlers.ofFileDownload(readWriteDir()); + } + + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void httpResponseBodyHandlersOfFileDownload_readOnly() { + HttpResponse.BodyHandlers.ofFileDownload(readDir()); + } + + @EntitlementTest(expectedAccess = PLUGINS) + static void httpResponseBodySubscribersOfFile_File() { + HttpResponse.BodySubscribers.ofFile(readWriteFile()); + } + + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void httpResponseBodySubscribersOfFile_File_readOnly() { + HttpResponse.BodySubscribers.ofFile(readFile()); + } + + @EntitlementTest(expectedAccess = PLUGINS) + static void httpResponseBodySubscribersOfFile_FileOpenOptions() { + // Note that, unlike other methods like BodyHandlers.ofFile, this is indeed + // an overload distinct from ofFile with no OpenOptions, and so it needs its + // own instrumentation and its own test. + HttpResponse.BodySubscribers.ofFile(readWriteFile(), CREATE, WRITE); + } + + @EntitlementTest(expectedAccess = ALWAYS_DENIED) + static void httpResponseBodySubscribersOfFile_FileOpenOptions_readOnly() { + // Note that, unlike other methods like BodyHandlers.ofFile, this is indeed + // an overload distinct from ofFile with no OpenOptions, and so it needs its + // own instrumentation and its own test. + HttpResponse.BodySubscribers.ofFile(readFile(), CREATE, WRITE); + } + private FileCheckActions() {} } diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/FileStoreActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/FileStoreActions.java index 0c8026ea9fee4..3482f267c53e8 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/FileStoreActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/FileStoreActions.java @@ -16,6 +16,7 @@ import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.ALWAYS_DENIED; import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.SERVER_ONLY; +@SuppressWarnings({ "unused" /* called via reflection */ }) class FileStoreActions { @EntitlementTest(expectedAccess = ALWAYS_DENIED) diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/ManageThreadsActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/ManageThreadsActions.java index 9850dfa201e46..e2a4a080dc5cc 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/ManageThreadsActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/ManageThreadsActions.java @@ -17,7 +17,7 @@ import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS; @SuppressForbidden(reason = "testing entitlements") -@SuppressWarnings("unused") // used via reflection +@SuppressWarnings({ "unused" /* called via reflaction */, "removal" }) class ManageThreadsActions { private ManageThreadsActions() {} diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NetworkAccessCheckActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NetworkAccessCheckActions.java index f0929894c262c..016e39200253d 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NetworkAccessCheckActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NetworkAccessCheckActions.java @@ -81,7 +81,7 @@ static void urlOpenConnectionWithProxy() throws URISyntaxException, IOException assert urlConnection != null; } - static void createLDAPCertStore() throws NoSuchAlgorithmException { + static void createLDAPCertStore() { try { // We pass down null params to provoke a InvalidAlgorithmParameterException CertStore.getInstance("LDAP", null); diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NioChannelsActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NioChannelsActions.java index 777f0fbf67a9f..c8271b843f87a 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NioChannelsActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NioChannelsActions.java @@ -23,6 +23,7 @@ import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.ALWAYS_DENIED; import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS; +@SuppressWarnings({ "unused" /* called via reflection */ }) class NioChannelsActions { @EntitlementTest(expectedAccess = ALWAYS_DENIED) @@ -51,7 +52,7 @@ static void fileChannelOpenForReadWithOptions() throws IOException { } @EntitlementTest(expectedAccess = ALWAYS_DENIED) - static void createAsynchronousFileChannel() throws IOException { + static void createAsynchronousFileChannel() { new DummyImplementations.DummyAsynchronousFileChannel().close(); } diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NioFileSystemActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NioFileSystemActions.java index de3a8cd645672..09ecad2126efc 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NioFileSystemActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NioFileSystemActions.java @@ -27,6 +27,7 @@ import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS; import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.SERVER_ONLY; +@SuppressWarnings({ "unused" /* called via reflection */ }) class NioFileSystemActions { @EntitlementTest(expectedAccess = SERVER_ONLY) diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NioFilesActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NioFilesActions.java index d4e8938b4b23e..b161c830e9bcf 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NioFilesActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/NioFilesActions.java @@ -39,6 +39,7 @@ import static org.elasticsearch.entitlement.qa.test.FileCheckActions.readWriteDir; import static org.elasticsearch.entitlement.qa.test.FileCheckActions.readWriteFile; +@SuppressWarnings({ "unused" /* called via reflection */ }) class NioFilesActions { @EntitlementTest(expectedAccess = PLUGINS) @@ -313,52 +314,36 @@ static void checkFilesIsExecutable() { @EntitlementTest(expectedAccess = PLUGINS) static void checkFilesWalkFileTree() throws IOException { - Files.walkFileTree(readDir(), new FileVisitor<>() { - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { - return FileVisitResult.SKIP_SUBTREE; - } - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - return FileVisitResult.SKIP_SUBTREE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { - return FileVisitResult.SKIP_SUBTREE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - return FileVisitResult.SKIP_SUBTREE; - } - }); + Files.walkFileTree(readDir(), dummyVisitor()); } @EntitlementTest(expectedAccess = PLUGINS) static void checkFilesWalkFileTreeWithOptions() throws IOException { - Files.walkFileTree(readDir(), Set.of(FileVisitOption.FOLLOW_LINKS), 2, new FileVisitor<>() { + Files.walkFileTree(readDir(), Set.of(FileVisitOption.FOLLOW_LINKS), 2, dummyVisitor()); + } + + private static FileVisitor dummyVisitor() { + return new FileVisitor<>() { @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { return FileVisitResult.SKIP_SUBTREE; } @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { return FileVisitResult.SKIP_SUBTREE; } @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + public FileVisitResult visitFileFailed(Path file, IOException exc) { return FileVisitResult.SKIP_SUBTREE; } @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + public FileVisitResult postVisitDirectory(Path dir, IOException exc) { return FileVisitResult.SKIP_SUBTREE; } - }); + }; } @EntitlementTest(expectedAccess = PLUGINS) diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/PathActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/PathActions.java index 5ccb0fa87ebda..b5b0c24d7c0a4 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/PathActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/PathActions.java @@ -16,6 +16,7 @@ import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.PLUGINS; +@SuppressWarnings({ "unused" /* called via reflection */, "rawtypes" }) class PathActions { @EntitlementTest(expectedAccess = PLUGINS) @@ -28,7 +29,6 @@ static void checkToRealPathNoFollow() throws IOException { FileCheckActions.readFile().toRealPath(LinkOption.NOFOLLOW_LINKS); } - @SuppressWarnings("rawtypes") @EntitlementTest(expectedAccess = PLUGINS) static void checkRegister() throws IOException { try (var watchService = FileSystems.getDefault().newWatchService()) { @@ -38,7 +38,6 @@ static void checkRegister() throws IOException { } } - @SuppressWarnings("rawtypes") @EntitlementTest(expectedAccess = PLUGINS) static void checkRegisterWithModifiers() throws IOException { try (var watchService = FileSystems.getDefault().newWatchService()) { diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/SpiActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/SpiActions.java index a335964c6fa81..aeb548c18fb69 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/SpiActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/SpiActions.java @@ -15,6 +15,7 @@ import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.ALWAYS_DENIED; +@SuppressWarnings({ "unused" /* called via reflection */ }) class SpiActions { @EntitlementTest(expectedAccess = ALWAYS_DENIED) static void createBreakIteratorProvider() { @@ -78,14 +79,7 @@ static void createLocaleServiceProvider() { @EntitlementTest(expectedAccess = ALWAYS_DENIED) static void getInheritedChannel() throws IOException { - Channel channel = null; - try { - channel = SelectorProvider.provider().inheritedChannel(); - } finally { - if (channel != null) { - channel.close(); - } - } + try (Channel channel = SelectorProvider.provider().inheritedChannel()) {} } @EntitlementTest(expectedAccess = ALWAYS_DENIED) diff --git a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/SystemActions.java b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/SystemActions.java index 4df1b1dd26d61..c1281f50365a9 100644 --- a/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/SystemActions.java +++ b/libs/entitlement/qa/entitlement-test-plugin/src/main/java/org/elasticsearch/entitlement/qa/test/SystemActions.java @@ -14,6 +14,7 @@ import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.ALWAYS_DENIED; import static org.elasticsearch.entitlement.qa.test.EntitlementTest.ExpectedAccess.SERVER_ONLY; +@SuppressWarnings({ "unused" /* called via reflection */ }) class SystemActions { @SuppressForbidden(reason = "Specifically testing Runtime.exit") diff --git a/libs/entitlement/src/main/java/module-info.java b/libs/entitlement/src/main/java/module-info.java index 697d26747b806..d6737a14a0b88 100644 --- a/libs/entitlement/src/main/java/module-info.java +++ b/libs/entitlement/src/main/java/module-info.java @@ -8,12 +8,13 @@ */ module org.elasticsearch.entitlement { + requires org.elasticsearch.base; requires org.elasticsearch.xcontent; requires org.elasticsearch.logging; requires java.instrument; - requires org.elasticsearch.base; - requires jdk.attach; + requires java.logging; requires java.net.http; + requires jdk.attach; requires jdk.net; requires static org.elasticsearch.entitlement.bridge; // At runtime, this will be in java.base diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java index 20fad76bfbfea..0f141cf515030 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/api/ElasticsearchEntitlementChecker.java @@ -89,6 +89,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.ForkJoinPool; import java.util.function.BiPredicate; +import java.util.logging.FileHandler; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; @@ -1758,6 +1759,78 @@ public void checkSelectorProviderInheritedChannel(Class callerClass, Selector policyManager.checkChangeJVMGlobalState(callerClass); } + @Override + public void check$java_util_logging_FileHandler$(Class callerClass) { + policyManager.checkLoggingFileHandler(callerClass); + } + + @Override + public void check$java_util_logging_FileHandler$(Class callerClass, String pattern) { + policyManager.checkLoggingFileHandler(callerClass); + } + + @Override + public void check$java_util_logging_FileHandler$(Class callerClass, String pattern, boolean append) { + policyManager.checkLoggingFileHandler(callerClass); + } + + @Override + public void check$java_util_logging_FileHandler$(Class callerClass, String pattern, int limit, int count) { + policyManager.checkLoggingFileHandler(callerClass); + } + + @Override + public void check$java_util_logging_FileHandler$(Class callerClass, String pattern, int limit, int count, boolean append) { + policyManager.checkLoggingFileHandler(callerClass); + } + + @Override + public void check$java_util_logging_FileHandler$(Class callerClass, String pattern, long limit, int count, boolean append) { + policyManager.checkLoggingFileHandler(callerClass); + } + + @Override + public void check$java_util_logging_FileHandler$close(Class callerClass, FileHandler that) { + // Note that there's no IT test for this one, because there's no way to create + // a FileHandler. However, we have this check just in case someone does manage + // to get their hands on a FileHandler and uses close() to cause its lock file to be deleted. + policyManager.checkLoggingFileHandler(callerClass); + } + + @Override + public void check$java_net_http_HttpRequest$BodyPublishers$$ofFile(Class callerClass, Path path) { + policyManager.checkFileRead(callerClass, path); + } + + @Override + public void check$java_net_http_HttpResponse$BodyHandlers$$ofFile(Class callerClass, Path path) { + policyManager.checkFileWrite(callerClass, path); + } + + @Override + public void check$java_net_http_HttpResponse$BodyHandlers$$ofFile(Class callerClass, Path path, OpenOption... options) { + policyManager.checkFileWrite(callerClass, path); + } + + @Override + public void check$java_net_http_HttpResponse$BodyHandlers$$ofFileDownload( + Class callerClass, + Path directory, + OpenOption... openOptions + ) { + policyManager.checkFileWrite(callerClass, directory); + } + + @Override + public void check$java_net_http_HttpResponse$BodySubscribers$$ofFile(Class callerClass, Path directory) { + policyManager.checkFileWrite(callerClass, directory); + } + + @Override + public void check$java_net_http_HttpResponse$BodySubscribers$$ofFile(Class callerClass, Path directory, OpenOption... openOptions) { + policyManager.checkFileWrite(callerClass, directory); + } + @Override public void checkNewFileSystem(Class callerClass, FileSystemProvider that, URI uri, Map env) { policyManager.checkChangeJVMGlobalState(callerClass); diff --git a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java index 66e44576b7452..2aafcfc594abd 100644 --- a/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java +++ b/libs/entitlement/src/main/java/org/elasticsearch/entitlement/runtime/policy/PolicyManager.java @@ -240,6 +240,10 @@ public void checkChangeJVMGlobalState(Class callerClass) { neverEntitled(callerClass, () -> walkStackForCheckMethodName().orElse("change JVM global state")); } + public void checkLoggingFileHandler(Class callerClass) { + neverEntitled(callerClass, () -> walkStackForCheckMethodName().orElse("create logging file handler")); + } + private Optional walkStackForCheckMethodName() { // Look up the check$ method to compose an informative error message. // This way, we don't need to painstakingly describe every individual global-state change. diff --git a/modules/ingest-geoip/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/ingest/geoip/FullClusterRestartIT.java b/modules/ingest-geoip/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/ingest/geoip/FullClusterRestartIT.java index 958f20f7981a0..fe11ee8691f39 100644 --- a/modules/ingest-geoip/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/ingest/geoip/FullClusterRestartIT.java +++ b/modules/ingest-geoip/qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/ingest/geoip/FullClusterRestartIT.java @@ -121,6 +121,9 @@ public void testGeoIpSystemFeaturesMigration() throws Exception { // as should a normal get * assertBusy(() -> testGetStar(List.of("my-index-00001"), List.of())); + + // and getting data streams + assertBusy(() -> testGetDatastreams()); } else { // after the upgrade, but before the migration, Kibana should work assertBusy(() -> testGetStarAsKibana(List.of("my-index-00001"), maybeSecurityIndex)); @@ -128,6 +131,9 @@ public void testGeoIpSystemFeaturesMigration() throws Exception { // as should a normal get * assertBusy(() -> testGetStar(List.of("my-index-00001"), maybeSecurityIndex)); + // and getting data streams + assertBusy(() -> testGetDatastreams()); + // migrate the system features and give the cluster a moment to settle Request migrateSystemFeatures = new Request("POST", "/_migration/system_features"); assertOK(client().performRequest(migrateSystemFeatures)); @@ -142,6 +148,9 @@ public void testGeoIpSystemFeaturesMigration() throws Exception { // as should a normal get * assertBusy(() -> testGetStar(List.of("my-index-00001"), maybeSecurityIndex)); + // and getting data streams + assertBusy(() -> testGetDatastreams()); + Request disableDownloader = new Request("PUT", "/_cluster/settings"); disableDownloader.setJsonEntity(""" {"persistent": {"ingest.geoip.downloader.enabled": false}} @@ -255,4 +264,15 @@ private void testGetStarAsKibana(List indexNames, @Nullable List Map map = responseAsMap(response); assertThat(map.keySet(), is(new HashSet<>(indexNames))); } + + private void testGetDatastreams() throws IOException { + Request getStar = new Request("GET", "_data_stream"); + getStar.setOptions( + RequestOptions.DEFAULT.toBuilder().setWarningsHandler(WarningsHandler.PERMISSIVE) // we don't care about warnings, just errors + ); + Response response = client().performRequest(getStar); + assertOK(response); + + // note: we don't actually care about the response, just that there was one and that it didn't error out on us + } } diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolver.java b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolver.java index fe7199f8332d2..562d2363905d4 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolver.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolver.java @@ -14,6 +14,7 @@ import org.elasticsearch.common.regex.Regex; import org.elasticsearch.core.Nullable; import org.elasticsearch.core.Tuple; +import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.indices.SystemIndices.SystemIndexAccessLevel; @@ -158,7 +159,26 @@ public static boolean isIndexVisible( if (indexAbstraction.isSystem()) { // check if it is net new if (resolver.getNetNewSystemIndexPredicate().test(indexAbstraction.getName())) { - return isSystemIndexVisible(resolver, indexAbstraction); + // don't give this code any particular credit for being *correct*. it's just trying to resolve a combination of + // issues in a way that happens to *work*. there's probably a better way of writing things such that this won't + // be necessary, but for the moment, it happens to be expedient to write things this way. + + // unwrap the alias and re-run the function on the write index of the alias -- that is, the alias is visible if + // the concrete index that it refers to is visible + Index writeIndex = indexAbstraction.getWriteIndex(); + if (writeIndex == null) { + return false; + } else { + return isIndexVisible( + expression, + selectorString, + writeIndex.getName(), + indicesOptions, + metadata, + resolver, + includeDataStreams + ); + } } } diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolverTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolverTests.java index de18fc32216a0..0f346ff0b2326 100644 --- a/server/src/test/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolverTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/metadata/IndexAbstractionResolverTests.java @@ -29,6 +29,7 @@ import java.util.function.Supplier; import static org.elasticsearch.index.mapper.MapperService.SINGLE_MAPPING_NAME; +import static org.elasticsearch.indices.SystemIndices.EXTERNAL_SYSTEM_INDEX_ACCESS_CONTROL_HEADER_KEY; import static org.elasticsearch.indices.SystemIndices.SYSTEM_INDEX_ACCESS_CONTROL_HEADER_KEY; import static org.elasticsearch.xcontent.XContentFactory.jsonBuilder; import static org.hamcrest.Matchers.contains; @@ -218,18 +219,6 @@ public void testIsIndexVisible() { assertThat(isIndexVisible("data-stream1", "failures"), is(true)); } - private boolean isIndexVisible(String index, String selector) { - return IndexAbstractionResolver.isIndexVisible( - "*", - selector, - index, - IndicesOptions.strictExpandHidden(), - metadata, - indexNameExpressionResolver, - true - ); - } - public void testIsNetNewSystemIndexVisible() { final Settings settings = Settings.builder() .put("index.number_of_replicas", 0) @@ -271,16 +260,71 @@ public void testIsNetNewSystemIndexVisible() { List.of(new SystemIndices.Feature("name", "description", List.of(fooDescriptor, barDescriptor))) ); - final ThreadContext threadContext = new ThreadContext(Settings.EMPTY); - threadContext.putHeader(SYSTEM_INDEX_ACCESS_CONTROL_HEADER_KEY, "false"); - indexNameExpressionResolver = new IndexNameExpressionResolver(threadContext, systemIndices); - indexAbstractionResolver = new IndexAbstractionResolver(indexNameExpressionResolver); - metadata = Metadata.builder().put(foo, true).put(barReindexed, true).put(other, true).build(); - assertThat(isIndexVisible("other", "*"), is(true)); - assertThat(isIndexVisible(".foo", "*"), is(false)); - assertThat(isIndexVisible(".bar", "*"), is(false)); + // these indices options are for the GET _data_streams case + final IndicesOptions noHiddenNoAliases = IndicesOptions.builder() + .wildcardOptions( + IndicesOptions.WildcardOptions.builder() + .matchOpen(true) + .matchClosed(true) + .includeHidden(false) + .resolveAliases(false) + .build() + ) + .build(); + + { + final ThreadContext threadContext = new ThreadContext(Settings.EMPTY); + threadContext.putHeader(SYSTEM_INDEX_ACCESS_CONTROL_HEADER_KEY, "true"); + indexNameExpressionResolver = new IndexNameExpressionResolver(threadContext, systemIndices); + indexAbstractionResolver = new IndexAbstractionResolver(indexNameExpressionResolver); + + // this covers the GET * case -- with system access, you can see everything + assertThat(isIndexVisible("other", "*"), is(true)); + assertThat(isIndexVisible(".foo", "*"), is(true)); + assertThat(isIndexVisible(".bar", "*"), is(true)); + + // but if you don't ask for hidden and aliases, you won't see hidden indices or aliases, naturally + assertThat(isIndexVisible("other", "*", noHiddenNoAliases), is(true)); + assertThat(isIndexVisible(".foo", "*", noHiddenNoAliases), is(false)); + assertThat(isIndexVisible(".bar", "*", noHiddenNoAliases), is(false)); + } + + { + final ThreadContext threadContext = new ThreadContext(Settings.EMPTY); + threadContext.putHeader(SYSTEM_INDEX_ACCESS_CONTROL_HEADER_KEY, "false"); + indexNameExpressionResolver = new IndexNameExpressionResolver(threadContext, systemIndices); + indexAbstractionResolver = new IndexAbstractionResolver(indexNameExpressionResolver); + + // this covers the GET * case -- without system access, you can't see everything + assertThat(isIndexVisible("other", "*"), is(true)); + assertThat(isIndexVisible(".foo", "*"), is(false)); + assertThat(isIndexVisible(".bar", "*"), is(false)); + + // no difference here in the datastream case, you can't see these then, either + assertThat(isIndexVisible("other", "*", noHiddenNoAliases), is(true)); + assertThat(isIndexVisible(".foo", "*", noHiddenNoAliases), is(false)); + assertThat(isIndexVisible(".bar", "*", noHiddenNoAliases), is(false)); + } + + { + final ThreadContext threadContext = new ThreadContext(Settings.EMPTY); + threadContext.putHeader(SYSTEM_INDEX_ACCESS_CONTROL_HEADER_KEY, "true"); + threadContext.putHeader(EXTERNAL_SYSTEM_INDEX_ACCESS_CONTROL_HEADER_KEY, "some-elastic-product"); + indexNameExpressionResolver = new IndexNameExpressionResolver(threadContext, systemIndices); + indexAbstractionResolver = new IndexAbstractionResolver(indexNameExpressionResolver); + + // this covers the GET * case -- with product (only) access, you can't see everything + assertThat(isIndexVisible("other", "*"), is(true)); + assertThat(isIndexVisible(".foo", "*"), is(false)); + assertThat(isIndexVisible(".bar", "*"), is(false)); + + // no difference here in the datastream case, you can't see these then, either + assertThat(isIndexVisible("other", "*", noHiddenNoAliases), is(true)); + assertThat(isIndexVisible(".foo", "*", noHiddenNoAliases), is(false)); + assertThat(isIndexVisible(".bar", "*", noHiddenNoAliases), is(false)); + } } private static XContentBuilder mappings() { @@ -308,4 +352,12 @@ private List resolveAbstractionsSelectorAllowed(List expressions private List resolveAbstractions(List expressions, IndicesOptions indicesOptions, Supplier> mask) { return indexAbstractionResolver.resolveIndexAbstractions(expressions, indicesOptions, metadata, mask, (idx) -> true, true); } + + private boolean isIndexVisible(String index, String selector) { + return isIndexVisible(index, selector, IndicesOptions.strictExpandHidden()); + } + + private boolean isIndexVisible(String index, String selector, IndicesOptions indicesOptions) { + return IndexAbstractionResolver.isIndexVisible("*", selector, index, indicesOptions, metadata, indexNameExpressionResolver, true); + } } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/InferenceNamedWriteablesProvider.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/InferenceNamedWriteablesProvider.java index e8dc763116707..2ff9fead27ec9 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/InferenceNamedWriteablesProvider.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/InferenceNamedWriteablesProvider.java @@ -57,6 +57,7 @@ import org.elasticsearch.xpack.inference.services.cohere.rerank.CohereRerankServiceSettings; import org.elasticsearch.xpack.inference.services.cohere.rerank.CohereRerankTaskSettings; import org.elasticsearch.xpack.inference.services.elastic.ElasticInferenceServiceSparseEmbeddingsServiceSettings; +import org.elasticsearch.xpack.inference.services.elastic.completion.ElasticInferenceServiceCompletionServiceSettings; import org.elasticsearch.xpack.inference.services.elasticsearch.CustomElandInternalServiceSettings; import org.elasticsearch.xpack.inference.services.elasticsearch.CustomElandInternalTextEmbeddingServiceSettings; import org.elasticsearch.xpack.inference.services.elasticsearch.ElasticRerankerServiceSettings; @@ -618,5 +619,12 @@ private static void addEisNamedWriteables(List nam ElasticInferenceServiceSparseEmbeddingsServiceSettings::new ) ); + namedWriteables.add( + new NamedWriteableRegistry.Entry( + ServiceSettings.class, + ElasticInferenceServiceCompletionServiceSettings.NAME, + ElasticInferenceServiceCompletionServiceSettings::new + ) + ); } }