Merge branch 'stable-2.11'
* stable-2.11: Add documentation for SecureStore Add SwitchSecureStore site program Make SecureStore an abstract class Add API to make SecureStore switching possible Change-Id: I60f6e58f590a94004329bf663506923a95c3a500
This commit is contained in:
@@ -43,7 +43,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
@@ -134,11 +134,14 @@ public class JarScanner implements PluginContentScanner {
|
||||
return result.build();
|
||||
}
|
||||
|
||||
public List<String> findImplementationsOf(Class<?> requestedInterface)
|
||||
throws IOException {
|
||||
List<String> result = Lists.newArrayList();
|
||||
String name = requestedInterface.getName().replace('.', '/');
|
||||
public List<String> findSubClassesOf(Class<?> superClass) throws IOException {
|
||||
return findSubClassesOf(superClass.getName());
|
||||
}
|
||||
|
||||
private List<String> findSubClassesOf(String superClass) throws IOException {
|
||||
String name = superClass.replace('.', '/');
|
||||
|
||||
List<String> classes = new ArrayList<>();
|
||||
Enumeration<JarEntry> e = jarFile.entries();
|
||||
while (e.hasMoreElements()) {
|
||||
JarEntry entry = e.nextElement();
|
||||
@@ -155,13 +158,15 @@ public class JarScanner implements PluginContentScanner {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (def.isConcrete() && def.interfaces != null
|
||||
&& Iterables.contains(Arrays.asList(def.interfaces), name)) {
|
||||
result.add(def.className);
|
||||
if (name.equals(def.superName)) {
|
||||
classes.addAll(findSubClassesOf(def.className));
|
||||
if (def.isConcrete()) {
|
||||
classes.add(def.className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return classes;
|
||||
}
|
||||
|
||||
private static boolean skip(JarEntry entry) {
|
||||
@@ -192,6 +197,7 @@ public class JarScanner implements PluginContentScanner {
|
||||
public static class ClassData extends ClassVisitor {
|
||||
int access;
|
||||
String className;
|
||||
String superName;
|
||||
String annotationName;
|
||||
String annotationValue;
|
||||
String[] interfaces;
|
||||
@@ -212,7 +218,7 @@ public class JarScanner implements PluginContentScanner {
|
||||
String superName, String[] interfaces) {
|
||||
this.className = Type.getObjectType(name).getClassName();
|
||||
this.access = access;
|
||||
this.interfaces = interfaces;
|
||||
this.superName = superName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,10 +26,11 @@ import org.eclipse.jgit.util.FS;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Singleton
|
||||
public class DefaultSecureStore implements SecureStore {
|
||||
public class DefaultSecureStore extends SecureStore {
|
||||
private final FileBasedConfig sec;
|
||||
|
||||
@Inject
|
||||
@@ -43,26 +44,11 @@ public class DefaultSecureStore implements SecureStore {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get(String section, String subsection, String name) {
|
||||
return sec.getString(section, subsection, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getList(String section, String subsection, String name) {
|
||||
return sec.getStringList(section, subsection, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String section, String subsection, String name, String value) {
|
||||
if (value != null) {
|
||||
sec.setString(section, subsection, name, value);
|
||||
} else {
|
||||
sec.unset(section, subsection, name);
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setList(String section, String subsection, String name,
|
||||
List<String> values) {
|
||||
@@ -80,6 +66,22 @@ public class DefaultSecureStore implements SecureStore {
|
||||
save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<EntryKey> list() {
|
||||
List<EntryKey> result = new ArrayList<>();
|
||||
for (String section : sec.getSections()) {
|
||||
for (String subsection : sec.getSubsections(section)) {
|
||||
for (String name : sec.getNames(section, subsection)) {
|
||||
result.add(new EntryKey(section, subsection, name));
|
||||
}
|
||||
}
|
||||
for (String name : sec.getNames(section)) {
|
||||
result.add(new EntryKey(section, null, name));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void save() {
|
||||
try {
|
||||
saveSecure(sec);
|
||||
|
||||
@@ -14,17 +14,115 @@
|
||||
|
||||
package com.google.gerrit.server.securestore;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SecureStore {
|
||||
/**
|
||||
* Abstract class for providing new SecureStore implementation for Gerrit.
|
||||
*
|
||||
* SecureStore is responsible for storing sensitive data like passwords in a
|
||||
* secure manner.
|
||||
*
|
||||
* It is implementator's responsibility to encrypt and store values.
|
||||
*
|
||||
* To deploy new SecureStore one needs to provide a jar file with explicitly one
|
||||
* class that extends {@code SecureStore} and put it in Gerrit server. Then run:
|
||||
*
|
||||
* `java -jar gerrit.war SwitchSecureStore -d $gerrit_site --new-secure-store-lib
|
||||
* $path_to_new_secure_store.jar`
|
||||
*
|
||||
* on stopped Gerrit instance.
|
||||
*/
|
||||
public abstract class SecureStore {
|
||||
/**
|
||||
* Describes {@link SecureStore} entry
|
||||
*/
|
||||
public static class EntryKey {
|
||||
public final String name;
|
||||
public final String section;
|
||||
public final String subsection;
|
||||
|
||||
String get(String section, String subsection, String name);
|
||||
/**
|
||||
* Creates EntryKey.
|
||||
*
|
||||
* @param section
|
||||
* @param subsection
|
||||
* @param name
|
||||
*/
|
||||
public EntryKey(String section, String subsection, String name) {
|
||||
this.name = name;
|
||||
this.section = section;
|
||||
this.subsection = subsection;
|
||||
}
|
||||
}
|
||||
|
||||
String[] getList(String section, String subsection, String name);
|
||||
/**
|
||||
* Extract decrypted value of stored property from SecureStore or {@code null}
|
||||
* when property was not found.
|
||||
*
|
||||
* @param section
|
||||
* @param subsection
|
||||
* @param name
|
||||
* @return decrypted String value or {@code null} if not found
|
||||
*/
|
||||
public final String get(String section, String subsection, String name) {
|
||||
String[] values = getList(section, subsection, name);
|
||||
if (values != null && values.length > 0) {
|
||||
return values[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void set(String section, String subsection, String name, String value);
|
||||
/**
|
||||
* Extract list of values from SecureStore and decrypt every value in that
|
||||
* list or {@code null} when property was not found.
|
||||
*
|
||||
* @param section
|
||||
* @param subsection
|
||||
* @param name
|
||||
* @return decrypted list of string values or {@code null}
|
||||
*/
|
||||
public abstract String[] getList(String section, String subsection, String name);
|
||||
|
||||
void setList(String section, String subsection, String name, List<String> values);
|
||||
/**
|
||||
* Store single value in SecureStore.
|
||||
*
|
||||
* This method is responsible for encrypting value and storing it.
|
||||
*
|
||||
* @param section
|
||||
* @param subsection
|
||||
* @param name
|
||||
* @param value plain text value
|
||||
*/
|
||||
public final void set(String section, String subsection, String name, String value) {
|
||||
setList(section, subsection, name, Lists.newArrayList(value));
|
||||
}
|
||||
|
||||
void unset(String section, String subsection, String name);
|
||||
/**
|
||||
* Store list of values in SecureStore.
|
||||
*
|
||||
* This method is responsible for encrypting all values in the list and storing them.
|
||||
*
|
||||
* @param section
|
||||
* @param subsection
|
||||
* @param name
|
||||
* @param values list of plain text values
|
||||
*/
|
||||
public abstract void setList(String section, String subsection, String name, List<String> values);
|
||||
|
||||
/**
|
||||
* Remove value for given {@code section}, {@code subsection} and {@code name}
|
||||
* from SecureStore.
|
||||
*
|
||||
* @param section
|
||||
* @param subsection
|
||||
* @param name
|
||||
*/
|
||||
public abstract void unset(String section, String subsection, String name);
|
||||
|
||||
/**
|
||||
* @return list of stored entries.
|
||||
*/
|
||||
public abstract Iterable<EntryKey> list();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user