diff --git a/pom.xml b/pom.xml
index 18704d525..6bb351e10 100644
--- a/pom.xml
+++ b/pom.xml
@@ -452,5 +452,17 @@
javax.annotation-api
1.3.2
+
+ org.xerial
+ sqlite-jdbc
+ 3.36.0.1
+
+
+
+ org.yaml
+ snakeyaml
+ 1.29
+
+
diff --git a/src/main/java/org/gaul/s3proxy/Main.java b/src/main/java/org/gaul/s3proxy/Main.java
index 8d86f3f0e..7e74b413d 100644
--- a/src/main/java/org/gaul/s3proxy/Main.java
+++ b/src/main/java/org/gaul/s3proxy/Main.java
@@ -16,22 +16,6 @@
package org.gaul.s3proxy;
-import java.io.Console;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -39,7 +23,10 @@
import com.google.common.io.Files;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.inject.Module;
-
+import org.gaul.s3proxy.extend.AbStractAKSKManager;
+import org.gaul.s3proxy.extend.AkSkPair;
+import org.gaul.s3proxy.extend.SqliteAKSKManager;
+import org.gaul.s3proxy.extend.YamlAKSKManager;
import org.jclouds.Constants;
import org.jclouds.ContextBuilder;
import org.jclouds.JcloudsVersion;
@@ -56,8 +43,17 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
public final class Main {
private static final Logger logger = LoggerFactory.getLogger(Main.class);
+
private Main() {
throw new AssertionError("intentionally not implemented");
}
@@ -69,8 +65,27 @@ private static final class Options {
@Option(name = "--version", usage = "display version")
private boolean version;
+
+ @Option(name = "--enable_bucket_ak_sk",
+ usage = "experimental feature to provide different ak/sk for per bucket"
+ )
+ private boolean enableBucketAkSk;
+
+ @Option(name = "--config_store",
+ usage = "yaml,sqlite.. etc."
+ )
+ private String configStoreType = "yaml";
+
+
+ @Option(name = "--config_path",
+ usage = "config file path. for sqlite is db file path, and for yaml is local yml file absolute path."
+ )
+ private String configPath = "";
+ ;
+
}
+
public static void main(String[] args) throws Exception {
Console console = System.console();
if (console == null) {
@@ -100,8 +115,26 @@ public static void main(String[] args) throws Exception {
.build();
ExecutorService executorService = DynamicExecutors.newScalingThreadPool(
1, 20, 60 * 1000, factory);
- ImmutableMap.Builder> locators =
- ImmutableMap.builder();
+ Map> locators =
+ new LinkedHashMap<>();
+ // load bucket access db
+ AbStractAKSKManager accessSecretManager = null;
+ Map accessCache = null;
+ if (options.enableBucketAkSk) {
+ switch (options.configStoreType) {
+ case "sqlite":
+ accessSecretManager = new SqliteAKSKManager(options.configPath);
+ break;
+ case "yaml":
+ accessSecretManager = new YamlAKSKManager(options.configPath);
+ break;
+ default:
+ accessSecretManager = new YamlAKSKManager(options.configPath);
+ }
+ accessCache = accessSecretManager.getBucketAkSkList();
+
+ }
+
for (File propertiesFile : options.propertiesFiles) {
Properties properties = new Properties();
try (InputStream is = new FileInputStream(propertiesFile)) {
@@ -111,6 +144,7 @@ public static void main(String[] args) throws Exception {
BlobStore blobStore = createBlobStore(properties, executorService);
+
blobStore = parseMiddlewareProperties(blobStore, executorService,
properties);
@@ -122,8 +156,20 @@ public static void main(String[] args) throws Exception {
S3ProxyConstants.PROPERTY_IDENTITY);
String localCredential = properties.getProperty(
S3ProxyConstants.PROPERTY_CREDENTIAL);
+ Map> save = new HashMap<>();
locators.put(localIdentity, Maps.immutableEntry(
localCredential, blobStore));
+ // register blobStore to access manager
+ if (accessSecretManager != null) {
+ accessSecretManager.registerBlobStore(blobStore);
+ }
+ if (accessCache != null) {
+ for (Map.Entry entry : accessCache.entrySet()) {
+ // add sqlite access key to locators
+ locators.put(entry.getValue().getAccess_key(), Maps.immutableEntry(
+ entry.getValue().getSecret_key(), blobStore));
+ }
+ }
}
S3Proxy.Builder s3ProxyBuilder2 = S3Proxy.Builder
@@ -139,6 +185,7 @@ public static void main(String[] args) throws Exception {
s3ProxyBuilder = s3ProxyBuilder2;
}
+
S3Proxy s3Proxy;
try {
s3Proxy = s3ProxyBuilder.build();
@@ -149,8 +196,12 @@ public static void main(String[] args) throws Exception {
}
final Map> locator =
- locators.build();
+ locators;
+ if (accessSecretManager != null) {
+ accessSecretManager.setLocator(locator);
+ }
if (!locator.isEmpty()) {
+ AbStractAKSKManager finalAbStractAKSKManager = accessSecretManager;
s3Proxy.setBlobStoreLocator(new BlobStoreLocator() {
@Override
public Map.Entry locateBlobStore(
@@ -161,10 +212,22 @@ public Map.Entry locateBlobStore(
.getValue();
}
throw new IllegalArgumentException(
- "cannot use anonymous access with multiple" +
- " backends");
+ "cannot use anonymous access with multiple" +
+ " backends");
+ }
+ // verify key
+ Map.Entry provider = locator.get(identity);
+ if (finalAbStractAKSKManager != null) {
+ String bucket = finalAbStractAKSKManager.getBucketFromAccessKey(identity);
+ if (!bucket.equalsIgnoreCase("")) {
+ // if bucket and access_key not match. [1:1 in db] return null
+ if (!container.equalsIgnoreCase(bucket)) {
+ return null;
+ }
+ }
}
- return locator.get(identity);
+
+ return provider;
}
});
}
@@ -178,7 +241,7 @@ public Map.Entry locateBlobStore(
}
private static BlobStore parseMiddlewareProperties(BlobStore blobStore,
- ExecutorService executorService, Properties properties)
+ ExecutorService executorService, Properties properties)
throws IOException {
Properties altProperties = new Properties();
for (Map.Entry