CASSANDRASC-71: Allow configuring permissions for uploaded SSTables
This commit introduces a new configuration for SSTable uploads (`file_permissions`) which allows
an operator to configure the desired file permissions used for files that are uploaded via SSTable
upload.
Patch by Francisco Guerrero; Reviewed by Dinesh Joshi, Yifan Cai for CASSANDRASC-71
diff --git a/CHANGES.txt b/CHANGES.txt
index 9c330d6..f7d0831 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,6 @@
1.0.0
-----
+ * Allow configuring permissions for uploaded SSTables (CASSANDRASC-71)
* Refactor Sidecar configuration (CASSANDRASC-69)
* Add Client Methods for Obtaining Sidecar and Cassandra Health (CASSANDRASC-70)
* Publish bytes streamed and written metrics (CASSANDRASC-68)
diff --git a/src/main/dist/conf/sidecar.yaml b/src/main/dist/conf/sidecar.yaml
index 2342c87..ddd9adc 100644
--- a/src/main/dist/conf/sidecar.yaml
+++ b/src/main/dist/conf/sidecar.yaml
@@ -75,6 +75,7 @@
sstable_upload:
concurrent_upload_limit: 80
min_free_space_percent: 10
+ # file_permissions: "rw-r--r--" # when not specified, the default file permissions are owner read & write, group & others read
allowable_time_skew_in_minutes: 60
sstable_import:
poll_interval_millis: 100
diff --git a/src/main/java/org/apache/cassandra/sidecar/config/SSTableUploadConfiguration.java b/src/main/java/org/apache/cassandra/sidecar/config/SSTableUploadConfiguration.java
index dd8df66..f36620c 100644
--- a/src/main/java/org/apache/cassandra/sidecar/config/SSTableUploadConfiguration.java
+++ b/src/main/java/org/apache/cassandra/sidecar/config/SSTableUploadConfiguration.java
@@ -18,6 +18,8 @@
package org.apache.cassandra.sidecar.config;
+import java.nio.file.attribute.PosixFilePermission;
+
/**
* Configuration for SSTable component uploads on this service
*/
@@ -32,4 +34,15 @@
* @return the configured minimum space percentage required for an SSTable component upload
*/
float minimumSpacePercentageRequired();
+
+ /**
+ * Returns the String representation of a set of posix file permissions used during an SSTable file upload.
+ * When an SSTable file is created the specified permissions will be used to create the file.
+ * For example, the String {@code rw-r--r--} represents the set of permissions
+ * {@link PosixFilePermission#OWNER_READ}, {@link PosixFilePermission#OWNER_WRITE},
+ * {@link PosixFilePermission#GROUP_READ}, and {@link PosixFilePermission#OTHERS_READ}.
+ *
+ * @return the String representation of a set of posix file permissions used during an SSTable file upload
+ */
+ String filePermissions();
}
diff --git a/src/main/java/org/apache/cassandra/sidecar/config/yaml/SSTableUploadConfigurationImpl.java b/src/main/java/org/apache/cassandra/sidecar/config/yaml/SSTableUploadConfigurationImpl.java
index cea66cc..68a8a45 100644
--- a/src/main/java/org/apache/cassandra/sidecar/config/yaml/SSTableUploadConfigurationImpl.java
+++ b/src/main/java/org/apache/cassandra/sidecar/config/yaml/SSTableUploadConfigurationImpl.java
@@ -18,6 +18,8 @@
package org.apache.cassandra.sidecar.config.yaml;
+import java.nio.file.attribute.PosixFilePermissions;
+
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.cassandra.sidecar.config.SSTableUploadConfiguration;
@@ -28,39 +30,52 @@
{
public static final String CONCURRENT_UPLOAD_LIMIT_PROPERTY = "concurrent_upload_limit";
public static final int DEFAULT_CONCURRENT_UPLOAD_LIMIT = 80;
+
public static final String MIN_FREE_SPACE_PERCENT_PROPERTY = "min_free_space_percent";
public static final float DEFAULT_MIN_FREE_SPACE_PERCENT = 10;
+ public static final String FILE_PERMISSIONS_PROPERTY = "file_permissions";
+ public static final String DEFAULT_FILE_PERMISSIONS = "rw-r--r--";
+
@JsonProperty(value = CONCURRENT_UPLOAD_LIMIT_PROPERTY, defaultValue = DEFAULT_CONCURRENT_UPLOAD_LIMIT + "")
protected final int concurrentUploadsLimit;
@JsonProperty(value = MIN_FREE_SPACE_PERCENT_PROPERTY, defaultValue = DEFAULT_MIN_FREE_SPACE_PERCENT + "")
protected final float minimumSpacePercentageRequired;
+ protected String filePermissions;
+
public SSTableUploadConfigurationImpl()
{
- this(DEFAULT_CONCURRENT_UPLOAD_LIMIT, DEFAULT_MIN_FREE_SPACE_PERCENT);
+ this(DEFAULT_CONCURRENT_UPLOAD_LIMIT, DEFAULT_MIN_FREE_SPACE_PERCENT, DEFAULT_FILE_PERMISSIONS);
}
public SSTableUploadConfigurationImpl(int concurrentUploadsLimit)
{
- this(concurrentUploadsLimit, DEFAULT_MIN_FREE_SPACE_PERCENT);
+ this(concurrentUploadsLimit, DEFAULT_MIN_FREE_SPACE_PERCENT, DEFAULT_FILE_PERMISSIONS);
}
public SSTableUploadConfigurationImpl(float minimumSpacePercentageRequired)
{
- this(DEFAULT_CONCURRENT_UPLOAD_LIMIT, minimumSpacePercentageRequired);
+ this(DEFAULT_CONCURRENT_UPLOAD_LIMIT, minimumSpacePercentageRequired, DEFAULT_FILE_PERMISSIONS);
+ }
+
+ public SSTableUploadConfigurationImpl(String filePermissions)
+ {
+ this(DEFAULT_CONCURRENT_UPLOAD_LIMIT, DEFAULT_MIN_FREE_SPACE_PERCENT, filePermissions);
}
public SSTableUploadConfigurationImpl(int concurrentUploadsLimit,
- float minimumSpacePercentageRequired)
+ float minimumSpacePercentageRequired,
+ String filePermissions)
{
this.concurrentUploadsLimit = concurrentUploadsLimit;
this.minimumSpacePercentageRequired = minimumSpacePercentageRequired;
+ setFilePermissions(filePermissions);
}
/**
- * @return the maximum number of concurrent SSTable component uploads allowed for this service
+ * {@inheritDoc}
*/
@Override
@JsonProperty(value = CONCURRENT_UPLOAD_LIMIT_PROPERTY, defaultValue = DEFAULT_CONCURRENT_UPLOAD_LIMIT + "")
@@ -70,7 +85,7 @@
}
/**
- * @return the configured minimum space percentage required for an SSTable component upload
+ * {@inheritDoc}
*/
@Override
@JsonProperty(value = MIN_FREE_SPACE_PERCENT_PROPERTY, defaultValue = DEFAULT_MIN_FREE_SPACE_PERCENT + "")
@@ -78,4 +93,37 @@
{
return minimumSpacePercentageRequired;
}
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @JsonProperty(value = FILE_PERMISSIONS_PROPERTY, defaultValue = DEFAULT_FILE_PERMISSIONS)
+ public String filePermissions()
+ {
+ return filePermissions;
+ }
+
+ @JsonProperty(value = FILE_PERMISSIONS_PROPERTY, defaultValue = DEFAULT_FILE_PERMISSIONS)
+ public void setFilePermissions(String filePermissions)
+ {
+ if (filePermissions != null)
+ {
+ try
+ {
+ // forces a validation of the input
+ this.filePermissions = PosixFilePermissions.toString(PosixFilePermissions.fromString(filePermissions));
+ }
+ catch (IllegalArgumentException exception)
+ {
+ String errorMessage = String.format("Invalid file_permissions configuration=\"%s\"", filePermissions);
+ throw new IllegalArgumentException(errorMessage);
+ }
+ }
+ else
+ {
+ this.filePermissions = null;
+ }
+ }
}
diff --git a/src/main/java/org/apache/cassandra/sidecar/routes/sstableuploads/SSTableUploadHandler.java b/src/main/java/org/apache/cassandra/sidecar/routes/sstableuploads/SSTableUploadHandler.java
index d14d5b1..b81f622 100644
--- a/src/main/java/org/apache/cassandra/sidecar/routes/sstableuploads/SSTableUploadHandler.java
+++ b/src/main/java/org/apache/cassandra/sidecar/routes/sstableuploads/SSTableUploadHandler.java
@@ -123,8 +123,11 @@
.compose(validRequest -> uploadPathBuilder.resolveStagingDirectory(host))
.compose(this::ensureSufficientSpaceAvailable)
.compose(v -> uploadPathBuilder.build(host, request))
- .compose(uploadDirectory -> uploader.uploadComponent(httpRequest, uploadDirectory, request.component(),
- request.expectedChecksum()))
+ .compose(uploadDirectory -> uploader.uploadComponent(httpRequest,
+ uploadDirectory,
+ request.component(),
+ request.expectedChecksum(),
+ configuration.filePermissions()))
.compose(fs::props)
.onSuccess(fileProps -> {
long serviceTimeMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTimeInNanos);
diff --git a/src/main/java/org/apache/cassandra/sidecar/utils/SSTableUploader.java b/src/main/java/org/apache/cassandra/sidecar/utils/SSTableUploader.java
index 6a5b271..0f21a47 100644
--- a/src/main/java/org/apache/cassandra/sidecar/utils/SSTableUploader.java
+++ b/src/main/java/org/apache/cassandra/sidecar/utils/SSTableUploader.java
@@ -67,19 +67,21 @@
* @param uploadDirectory the absolute path to the upload directory in the target {@code fs}
* @param componentFileName the file name of the component
* @param expectedChecksum for verifying upload integrity, passed in through request
+ * @param filePermissions specifies the posix file permissions used to create the SSTable file
* @return path of SSTable component to which data was uploaded
*/
public Future<String> uploadComponent(ReadStream<Buffer> readStream,
String uploadDirectory,
String componentFileName,
- String expectedChecksum)
+ String expectedChecksum,
+ String filePermissions)
{
String targetPath = StringUtils.removeEnd(uploadDirectory, File.separator)
+ File.separatorChar + componentFileName;
return fs.mkdirs(uploadDirectory) // ensure the parent directory is created
- .compose(v -> createTempFile(uploadDirectory, componentFileName)) // create a temporary file
+ .compose(v -> createTempFile(uploadDirectory, componentFileName, filePermissions))
.compose(tempFilePath -> streamAndVerify(readStream, tempFilePath, expectedChecksum))
.compose(verifiedTempFilePath -> moveAtomicallyWithFallBack(verifiedTempFilePath, targetPath));
}
@@ -102,11 +104,12 @@
}); // stream to file
}
- private Future<String> createTempFile(String uploadDirectory, String componentFileName)
+ private Future<String> createTempFile(String uploadDirectory, String componentFileName, String permissions)
{
- LOGGER.debug("Creating temp file in directory={} with name={}{}",
- uploadDirectory, componentFileName, DEFAULT_TEMP_SUFFIX);
- return fs.createTempFile(uploadDirectory, componentFileName, DEFAULT_TEMP_SUFFIX, /* perms */ (String) null);
+ LOGGER.debug("Creating temp file in directory={} with name={}{}, permissions={}",
+ uploadDirectory, componentFileName, DEFAULT_TEMP_SUFFIX, permissions);
+
+ return fs.createTempFile(uploadDirectory, componentFileName, DEFAULT_TEMP_SUFFIX, permissions);
}
private Future<String> moveAtomicallyWithFallBack(String source, String target)
diff --git a/src/test/java/org/apache/cassandra/sidecar/config/SidecarConfigurationTest.java b/src/test/java/org/apache/cassandra/sidecar/config/SidecarConfigurationTest.java
index 8ca2bde..8d8ed00 100644
--- a/src/test/java/org/apache/cassandra/sidecar/config/SidecarConfigurationTest.java
+++ b/src/test/java/org/apache/cassandra/sidecar/config/SidecarConfigurationTest.java
@@ -24,10 +24,12 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
+import com.fasterxml.jackson.databind.JsonMappingException;
import org.apache.cassandra.sidecar.config.yaml.SidecarConfigurationImpl;
import static org.apache.cassandra.sidecar.common.ResourceUtils.writeResourceToPath;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
/**
* Tests reading Sidecar {@link SidecarConfiguration} from YAML files
@@ -113,6 +115,28 @@
validateMultipleInstancesSidecarConfiguration(config, true);
}
+ @Test
+ void testFilePermissions() throws IOException
+ {
+ Path yamlPath = yaml("config/sidecar_file_permissions.yaml");
+ SidecarConfiguration config = SidecarConfigurationImpl.readYamlConfiguration(yamlPath);
+
+ assertThat(config).isNotNull();
+ assertThat(config.serviceConfiguration()).isNotNull();
+ assertThat(config.serviceConfiguration().ssTableUploadConfiguration()).isNotNull();
+ assertThat(config.serviceConfiguration().ssTableUploadConfiguration().filePermissions()).isEqualTo("rw-rw-rw-");
+ }
+
+ @Test
+ void testInvalidFilePermissions()
+ {
+ Path yamlPath = yaml("config/sidecar_invalid_file_permissions.yaml");
+ assertThatExceptionOfType(JsonMappingException.class)
+ .isThrownBy(() -> SidecarConfigurationImpl.readYamlConfiguration(yamlPath))
+ .withRootCauseInstanceOf(IllegalArgumentException.class)
+ .withMessageContaining("Invalid file_permissions configuration=\"not-valid\"");
+ }
+
void validateSingleInstanceSidecarConfiguration(SidecarConfiguration config)
{
assertThat(config.cassandraInstances()).isNotNull().hasSize(1);
diff --git a/src/test/java/org/apache/cassandra/sidecar/config/yaml/SSTableUploadConfigurationImplTest.java b/src/test/java/org/apache/cassandra/sidecar/config/yaml/SSTableUploadConfigurationImplTest.java
new file mode 100644
index 0000000..6a2c604
--- /dev/null
+++ b/src/test/java/org/apache/cassandra/sidecar/config/yaml/SSTableUploadConfigurationImplTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.sidecar.config.yaml;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+
+/**
+ * Unit tests to validate {@link SSTableUploadConfigurationImpl} inputs
+ */
+class SSTableUploadConfigurationImplTest
+{
+ @Test
+ void testNullFilePermissions()
+ {
+ SSTableUploadConfigurationImpl config = new SSTableUploadConfigurationImpl(null);
+ assertThat(config.filePermissions()).isNull();
+ }
+
+ @ParameterizedTest(name = "{index} => invalid permission string \"{0}\"")
+ @ValueSource(strings = { "", "aaaaaaaaa", "rwxaaaaaa", "rwx", "null" })
+ void filePermissionsFailsOnInvalidString(String value)
+ {
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> new SSTableUploadConfigurationImpl(value))
+ .withMessage("Invalid filePermissions configuration=\"" + value + "\"");
+ }
+
+ @ParameterizedTest(name = "{index} => valid permission string \"{0}\"")
+ @ValueSource(strings = { "---------", "rwx------", "rwxr--r--", "r-xr-xr-x", "r-xr-xrwx" })
+ void testValidFilePermission(String value)
+ {
+ SSTableUploadConfigurationImpl config = new SSTableUploadConfigurationImpl(value);
+ assertThat(config.filePermissions()).isEqualTo(value);
+ }
+}
diff --git a/src/test/java/org/apache/cassandra/sidecar/routes/sstableuploads/SSTableUploadHandlerTest.java b/src/test/java/org/apache/cassandra/sidecar/routes/sstableuploads/SSTableUploadHandlerTest.java
index 64f2986..3338bca 100644
--- a/src/test/java/org/apache/cassandra/sidecar/routes/sstableuploads/SSTableUploadHandlerTest.java
+++ b/src/test/java/org/apache/cassandra/sidecar/routes/sstableuploads/SSTableUploadHandlerTest.java
@@ -22,6 +22,8 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -44,6 +46,15 @@
import org.apache.cassandra.sidecar.common.http.SidecarHttpResponseStatus;
import org.apache.cassandra.sidecar.snapshots.SnapshotUtils;
+import static java.nio.file.attribute.PosixFilePermission.GROUP_EXECUTE;
+import static java.nio.file.attribute.PosixFilePermission.GROUP_READ;
+import static java.nio.file.attribute.PosixFilePermission.GROUP_WRITE;
+import static java.nio.file.attribute.PosixFilePermission.OTHERS_EXECUTE;
+import static java.nio.file.attribute.PosixFilePermission.OTHERS_READ;
+import static java.nio.file.attribute.PosixFilePermission.OTHERS_WRITE;
+import static java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE;
+import static java.nio.file.attribute.PosixFilePermission.OWNER_READ;
+import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
@@ -189,6 +200,42 @@
Files.size(Paths.get(FILE_TO_BE_UPLOADED)), HttpResponseStatus.OK.code(), false);
}
+ @Test
+ public void testFilePermissionOnUpload(VertxTestContext context) throws IOException
+ {
+ String uploadId = UUID.randomUUID().toString();
+ when(mockSSTableUploadConfiguration.filePermissions()).thenReturn("rwxr-xr-x");
+
+ sendUploadRequestAndVerify(null, context, uploadId, "ks", "tbl", "without-md5.db", "",
+ Files.size(Paths.get(FILE_TO_BE_UPLOADED)), HttpResponseStatus.OK.code(),
+ false, response -> {
+
+ Path path = temporaryFolder.toPath()
+ .resolve("staging")
+ .resolve(uploadId)
+ .resolve("ks")
+ .resolve("tbl")
+ .resolve("without-md5.db");
+
+ try
+ {
+ Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(path);
+ assertThat(permissions).contains(OWNER_READ,
+ OWNER_WRITE,
+ OWNER_EXECUTE,
+ GROUP_READ,
+ GROUP_EXECUTE,
+ OTHERS_READ,
+ OTHERS_EXECUTE);
+ assertThat(permissions).doesNotContain(GROUP_WRITE, OTHERS_WRITE);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
private void sendUploadRequestAndVerify(VertxTestContext context,
UUID uploadId,
String keyspace,
diff --git a/src/test/resources/config/sidecar_file_permissions.yaml b/src/test/resources/config/sidecar_file_permissions.yaml
new file mode 100644
index 0000000..d1aeabe
--- /dev/null
+++ b/src/test/resources/config/sidecar_file_permissions.yaml
@@ -0,0 +1,122 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# Cassandra SideCar configuration file
+#
+cassandra_instances:
+ - id: 1
+ host: localhost1
+ port: 9042
+ username: cassandra
+ password: cassandra
+ data_dirs:
+ - /ccm/test/node1/data0
+ - /ccm/test/node1/data1
+ staging_dir: /ccm/test/node1/sstable-staging
+ jmx_host: 127.0.0.1
+ jmx_port: 7100
+ jmx_ssl_enabled: false
+ # jmx_role:
+ # jmx_role_password:
+ - id: 2
+ host: localhost2
+ port: 9042
+ username: cassandra
+ password: cassandra
+ data_dirs:
+ - /ccm/test/node2/data0
+ - /ccm/test/node2/data1
+ staging_dir: /ccm/test/node2/sstable-staging
+ jmx_host: 127.0.0.1
+ jmx_port: 7200
+ jmx_ssl_enabled: false
+ # jmx_role:
+ # jmx_role_password:
+ - id: 3
+ host: localhost3
+ port: 9042
+ username: cassandra
+ password: cassandra
+ data_dirs:
+ - /ccm/test/node3/data0
+ - /ccm/test/node3/data1
+ staging_dir: /ccm/test/node3/sstable-staging
+ jmx_host: 127.0.0.1
+ jmx_port: 7300
+ jmx_ssl_enabled: false
+# jmx_role:
+# jmx_role_password:
+
+sidecar:
+ host: 0.0.0.0
+ port: 9043
+ request_idle_timeout_millis: 300000 # this field expects integer value
+ request_timeout_millis: 300000
+ throttle:
+ stream_requests_per_sec: 5000
+ delay_sec: 5
+ timeout_sec: 10
+ sstable_upload:
+ concurrent_upload_limit: 80
+ min_free_space_percent: 10
+ file_permissions: "rw-rw-rw-"
+ allowable_time_skew_in_minutes: 60
+ sstable_import:
+ poll_interval_millis: 100
+ cache:
+ expire_after_access_millis: 7200000 # 2 hours
+ maximum_size: 10000
+ worker_pools:
+ service:
+ name: "sidecar-worker-pool"
+ size: 20
+ max_execution_time_millis: 60000 # 60 seconds
+ internal:
+ name: "sidecar-internal-worker-pool"
+ size: 20
+ max_execution_time_millis: 900000 # 15 minutes
+
+#
+# Enable SSL configuration (Disabled by default)
+#
+# ssl:
+# enabled: true
+# keystore:
+# path: "path/to/keystore.p12"
+# password: password
+# truststore:
+# path: "path/to/truststore.p12"
+# password: password
+
+
+healthcheck:
+ poll_freq_millis: 30000
+
+cassandra_input_validation:
+ forbidden_keyspaces:
+ - system_schema
+ - system_traces
+ - system_distributed
+ - system
+ - system_auth
+ - system_views
+ - system_virtual_schema
+ allowed_chars_for_directory: "[a-zA-Z0-9_-]+"
+ allowed_chars_for_component_name: "[a-zA-Z0-9_-]+(.db|.cql|.json|.crc32|TOC.txt)"
+ allowed_chars_for_restricted_component_name: "[a-zA-Z0-9_-]+(.db|TOC.txt)"
diff --git a/src/test/resources/config/sidecar_invalid_file_permissions.yaml b/src/test/resources/config/sidecar_invalid_file_permissions.yaml
new file mode 100644
index 0000000..ce192ce
--- /dev/null
+++ b/src/test/resources/config/sidecar_invalid_file_permissions.yaml
@@ -0,0 +1,122 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# Cassandra SideCar configuration file
+#
+cassandra_instances:
+ - id: 1
+ host: localhost1
+ port: 9042
+ username: cassandra
+ password: cassandra
+ data_dirs:
+ - /ccm/test/node1/data0
+ - /ccm/test/node1/data1
+ staging_dir: /ccm/test/node1/sstable-staging
+ jmx_host: 127.0.0.1
+ jmx_port: 7100
+ jmx_ssl_enabled: false
+ # jmx_role:
+ # jmx_role_password:
+ - id: 2
+ host: localhost2
+ port: 9042
+ username: cassandra
+ password: cassandra
+ data_dirs:
+ - /ccm/test/node2/data0
+ - /ccm/test/node2/data1
+ staging_dir: /ccm/test/node2/sstable-staging
+ jmx_host: 127.0.0.1
+ jmx_port: 7200
+ jmx_ssl_enabled: false
+ # jmx_role:
+ # jmx_role_password:
+ - id: 3
+ host: localhost3
+ port: 9042
+ username: cassandra
+ password: cassandra
+ data_dirs:
+ - /ccm/test/node3/data0
+ - /ccm/test/node3/data1
+ staging_dir: /ccm/test/node3/sstable-staging
+ jmx_host: 127.0.0.1
+ jmx_port: 7300
+ jmx_ssl_enabled: false
+# jmx_role:
+# jmx_role_password:
+
+sidecar:
+ host: 0.0.0.0
+ port: 9043
+ request_idle_timeout_millis: 300000 # this field expects integer value
+ request_timeout_millis: 300000
+ throttle:
+ stream_requests_per_sec: 5000
+ delay_sec: 5
+ timeout_sec: 10
+ sstable_upload:
+ concurrent_upload_limit: 80
+ min_free_space_percent: 10
+ file_permissions: "not-valid"
+ allowable_time_skew_in_minutes: 60
+ sstable_import:
+ poll_interval_millis: 100
+ cache:
+ expire_after_access_millis: 7200000 # 2 hours
+ maximum_size: 10000
+ worker_pools:
+ service:
+ name: "sidecar-worker-pool"
+ size: 20
+ max_execution_time_millis: 60000 # 60 seconds
+ internal:
+ name: "sidecar-internal-worker-pool"
+ size: 20
+ max_execution_time_millis: 900000 # 15 minutes
+
+#
+# Enable SSL configuration (Disabled by default)
+#
+# ssl:
+# enabled: true
+# keystore:
+# path: "path/to/keystore.p12"
+# password: password
+# truststore:
+# path: "path/to/truststore.p12"
+# password: password
+
+
+healthcheck:
+ poll_freq_millis: 30000
+
+cassandra_input_validation:
+ forbidden_keyspaces:
+ - system_schema
+ - system_traces
+ - system_distributed
+ - system
+ - system_auth
+ - system_views
+ - system_virtual_schema
+ allowed_chars_for_directory: "[a-zA-Z0-9_-]+"
+ allowed_chars_for_component_name: "[a-zA-Z0-9_-]+(.db|.cql|.json|.crc32|TOC.txt)"
+ allowed_chars_for_restricted_component_name: "[a-zA-Z0-9_-]+(.db|TOC.txt)"
diff --git a/src/test/resources/config/sidecar_multiple_instances.yaml b/src/test/resources/config/sidecar_multiple_instances.yaml
index 4388cea..502b919 100644
--- a/src/test/resources/config/sidecar_multiple_instances.yaml
+++ b/src/test/resources/config/sidecar_multiple_instances.yaml
@@ -75,6 +75,7 @@
sstable_upload:
concurrent_upload_limit: 80
min_free_space_percent: 10
+ # file_permissions: "rw-r--r--" # when not specified, the default file permissions are owner read & write, group & others read
allowable_time_skew_in_minutes: 60
sstable_import:
poll_interval_millis: 100
@@ -89,7 +90,7 @@
internal:
name: "sidecar-internal-worker-pool"
size: 20
- max_execution_time_millis: 300000 # 5 minutes
+ max_execution_time_millis: 900000 # 15 minutes
#
# Enable SSL configuration (Disabled by default)