Skip to content

Commit 515f2f1

Browse files
committed
Ensure that azure stream has socket privileges (elastic#28751)
This is related to elastic#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 08cd1b7 commit 515f2f1

File tree

4 files changed

+60
-2
lines changed

4 files changed

+60
-2
lines changed

plugins/repository-azure/src/main/java/org/elasticsearch/cloud/azure/blobstore/util/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/main/java/org/elasticsearch/cloud/azure/storage/AzureStorageService.java

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

8383
void writeBlob(String account, LocationMode mode, String container, String blobName, InputStream inputStream, long blobSize) throws
8484
URISyntaxException, StorageException;
85+
86+
static InputStream giveSocketPermissionsToStream(InputStream stream) {
87+
return new InputStream() {
88+
@Override
89+
public int read() throws IOException {
90+
return SocketAccess.doPrivilegedIOException(stream::read);
91+
}
92+
93+
@Override
94+
public int read(byte[] b) throws IOException {
95+
return SocketAccess.doPrivilegedIOException(() -> stream.read(b));
96+
}
97+
98+
@Override
99+
public int read(byte[] b, int off, int len) throws IOException {
100+
return SocketAccess.doPrivilegedIOException(() -> stream.read(b, off, len));
101+
}
102+
};
103+
}
85104
}

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

Lines changed: 4 additions & 1 deletion
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;
@@ -292,7 +293,9 @@ public InputStream getInputStream(String account, LocationMode mode, String cont
292293
logger.trace("reading container [{}], blob [{}]", container, blob);
293294
CloudBlobClient client = this.getSelectedClient(account, mode);
294295
CloudBlockBlob blockBlobReference = client.getContainerReference(container).getBlockBlobReference(blob);
295-
return SocketAccess.doPrivilegedException(() -> blockBlobReference.openInputStream(null, null, generateOperationContext(account)));
296+
BlobInputStream stream = SocketAccess.doPrivilegedException(() ->
297+
blockBlobReference.openInputStream(null, null, generateOperationContext(account)));
298+
return AzureStorageService.giveSocketPermissionsToStream(stream);
296299
}
297300

298301
@Override

plugins/repository-azure/src/test/java/org/elasticsearch/cloud/azure/storage/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
@@ -169,4 +171,29 @@ public static boolean endsWithIgnoreCase(String str, String suffix) {
169171
String lcPrefix = suffix.toLowerCase(Locale.ROOT);
170172
return lcStr.equals(lcPrefix);
171173
}
174+
175+
private static class PermissionRequiringInputStream extends ByteArrayInputStream {
176+
177+
private PermissionRequiringInputStream(byte[] buf) {
178+
super(buf);
179+
}
180+
181+
@Override
182+
public synchronized int read() {
183+
AccessController.checkPermission(new SocketPermission("*", "connect"));
184+
return super.read();
185+
}
186+
187+
@Override
188+
public int read(byte[] b) throws IOException {
189+
AccessController.checkPermission(new SocketPermission("*", "connect"));
190+
return super.read(b);
191+
}
192+
193+
@Override
194+
public synchronized int read(byte[] b, int off, int len) {
195+
AccessController.checkPermission(new SocketPermission("*", "connect"));
196+
return super.read(b, off, len);
197+
}
198+
}
172199
}

0 commit comments

Comments
 (0)