Skip to content

Commit de2a0df

Browse files
authored
Ensure that azure stream has socket privileges (#28751)
This is related to #28662. It wraps the azure repository inputstream in an inputstream that ensures `read` calls have socket permissions. This is because the azure inputstream internally makes service calls.
1 parent 7715813 commit de2a0df

File tree

4 files changed

+62
-4
lines changed

4 files changed

+62
-4
lines changed

plugins/repository-azure/src/main/java/org/elasticsearch/repositories/azure/AzureStorageService.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,23 @@ void moveBlob(String account, LocationMode mode, String container, String source
6262

6363
void writeBlob(String account, LocationMode mode, String container, String blobName, InputStream inputStream, long blobSize) throws
6464
URISyntaxException, StorageException;
65+
66+
static InputStream giveSocketPermissionsToStream(InputStream stream) {
67+
return new InputStream() {
68+
@Override
69+
public int read() throws IOException {
70+
return SocketAccess.doPrivilegedIOException(stream::read);
71+
}
72+
73+
@Override
74+
public int read(byte[] b) throws IOException {
75+
return SocketAccess.doPrivilegedIOException(() -> stream.read(b));
76+
}
77+
78+
@Override
79+
public int read(byte[] b, int off, int len) throws IOException {
80+
return SocketAccess.doPrivilegedIOException(() -> stream.read(b, off, len));
81+
}
82+
};
83+
}
6584
}

plugins/repository-azure/src/main/java/org/elasticsearch/repositories/azure/AzureStorageServiceImpl.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.microsoft.azure.storage.RetryExponentialRetry;
2626
import com.microsoft.azure.storage.RetryPolicy;
2727
import com.microsoft.azure.storage.StorageException;
28+
import com.microsoft.azure.storage.blob.BlobInputStream;
2829
import com.microsoft.azure.storage.blob.BlobListingDetails;
2930
import com.microsoft.azure.storage.blob.BlobProperties;
3031
import com.microsoft.azure.storage.blob.CloudBlobClient;
@@ -249,12 +250,14 @@ public void deleteBlob(String account, LocationMode mode, String container, Stri
249250
}
250251

251252
@Override
252-
public InputStream getInputStream(String account, LocationMode mode, String container, String blob)
253-
throws URISyntaxException, StorageException {
253+
public InputStream getInputStream(String account, LocationMode mode, String container, String blob) throws URISyntaxException,
254+
StorageException {
254255
logger.trace("reading container [{}], blob [{}]", container, blob);
255256
CloudBlobClient client = this.getSelectedClient(account, mode);
256257
CloudBlockBlob blockBlobReference = client.getContainerReference(container).getBlockBlobReference(blob);
257-
return SocketAccess.doPrivilegedException(() -> blockBlobReference.openInputStream(null, null, generateOperationContext(account)));
258+
BlobInputStream is = SocketAccess.doPrivilegedException(() ->
259+
blockBlobReference.openInputStream(null, null, generateOperationContext(account)));
260+
return AzureStorageService.giveSocketPermissionsToStream(is);
258261
}
259262

260263
@Override

plugins/repository-azure/src/main/java/org/elasticsearch/repositories/azure/SocketAccess.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ public final class SocketAccess {
3939

4040
private SocketAccess() {}
4141

42+
public static <T> T doPrivilegedIOException(PrivilegedExceptionAction<T> operation) throws IOException {
43+
SpecialPermission.check();
44+
try {
45+
return AccessController.doPrivileged(operation);
46+
} catch (PrivilegedActionException e) {
47+
throw (IOException) e.getCause();
48+
}
49+
}
50+
4251
public static <T> T doPrivilegedException(PrivilegedExceptionAction<T> operation) throws StorageException, URISyntaxException {
4352
SpecialPermission.check();
4453
try {

plugins/repository-azure/src/test/java/org/elasticsearch/repositories/azure/AzureStorageServiceMock.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@
3232
import java.io.ByteArrayOutputStream;
3333
import java.io.IOException;
3434
import java.io.InputStream;
35+
import java.net.SocketPermission;
3536
import java.net.URISyntaxException;
3637
import java.nio.file.NoSuchFileException;
38+
import java.security.AccessController;
3739
import java.util.Locale;
3840
import java.util.Map;
3941
import java.util.concurrent.ConcurrentHashMap;
@@ -81,7 +83,7 @@ public InputStream getInputStream(String account, LocationMode mode, String cont
8183
if (!blobExists(account, mode, container, blob)) {
8284
throw new NoSuchFileException("missing blob [" + blob + "]");
8385
}
84-
return new ByteArrayInputStream(blobs.get(blob).toByteArray());
86+
return AzureStorageService.giveSocketPermissionsToStream(new PermissionRequiringInputStream(blobs.get(blob).toByteArray()));
8587
}
8688

8789
@Override
@@ -170,4 +172,29 @@ public static boolean endsWithIgnoreCase(String str, String suffix) {
170172
String lcPrefix = suffix.toLowerCase(Locale.ROOT);
171173
return lcStr.equals(lcPrefix);
172174
}
175+
176+
private static class PermissionRequiringInputStream extends ByteArrayInputStream {
177+
178+
private PermissionRequiringInputStream(byte[] buf) {
179+
super(buf);
180+
}
181+
182+
@Override
183+
public synchronized int read() {
184+
AccessController.checkPermission(new SocketPermission("*", "connect"));
185+
return super.read();
186+
}
187+
188+
@Override
189+
public int read(byte[] b) throws IOException {
190+
AccessController.checkPermission(new SocketPermission("*", "connect"));
191+
return super.read(b);
192+
}
193+
194+
@Override
195+
public synchronized int read(byte[] b, int off, int len) {
196+
AccessController.checkPermission(new SocketPermission("*", "connect"));
197+
return super.read(b, off, len);
198+
}
199+
}
173200
}

0 commit comments

Comments
 (0)