未验证 提交 dbdcaaf3 编写于 作者: J Jesse Glick

SecretRewriterTest

上级 4af739f2
...@@ -80,5 +80,5 @@ public class HistoricalSecrets { ...@@ -80,5 +80,5 @@ public class HistoricalSecrets {
return Util.toAes128Key(secret); return Util.toAes128Key(secret);
} }
private static final String MAGIC = "::::MAGIC::::"; static final String MAGIC = "::::MAGIC::::";
} }
package hudson.util
import com.trilead.ssh2.crypto.Base64
import hudson.FilePath
import hudson.Functions
import jenkins.security.ConfidentialStoreRule
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import javax.crypto.Cipher
import static org.junit.Assume.assumeFalse
/**
*
*
* @author Kohsuke Kawaguchi
*/
class SecretRewriterTest {
@Rule
public MockSecretRule mockSecretRule = new MockSecretRule()
@Rule
public ConfidentialStoreRule confidentialStoreRule = new ConfidentialStoreRule();
@Rule public TemporaryFolder tmp = new TemporaryFolder()
def FOO_PATTERN = /<foo>\{[A-Za-z0-9+\/]+={0,2}}<\/foo>/
def MSG_PATTERN = /<msg>\{[A-Za-z0-9+\/]+={0,2}}<\/msg>/
def FOO_PATTERN2 = /(<foo>\{[A-Za-z0-9+\/]+={0,2}}<\/foo>){2}/
def ABC_FOO_PATTERN = /<abc>\s<foo>\{[A-Za-z0-9+\/]+={0,2}}<\/foo>\s<\/abc>/
@Test
void singleFileRewrite() {
def o = encryptOld('foobar') // old
def n = encryptNew('foobar') // new
roundtrip "<foo>${o}</foo>",
{assert it ==~ FOO_PATTERN}
roundtrip "<foo>${o}</foo><foo>${o}</foo>",
{assert it ==~ FOO_PATTERN2}
roundtrip "<foo>${n}</foo>",
{assert it == "<foo>${n}</foo>"}
roundtrip " <foo>thisIsLegalBase64AndLongEnoughThatItCouldLookLikeSecret</foo> ",
{assert it == "<foo>thisIsLegalBase64AndLongEnoughThatItCouldLookLikeSecret</foo>"}
// to be rewritten, it needs to be between a tag
roundtrip "<foo>$o", {assert it == "<foo>$o"}
roundtrip "$o</foo>", {assert it == "$o</foo>"}
//
roundtrip "<abc>\n<foo>$o</foo>\n</abc>", {assert it ==~ ABC_FOO_PATTERN}
}
void roundtrip(String before, Closure check) {
def sr = new SecretRewriter(null);
def f = File.createTempFile("test", "xml", tmp.root)
f.text = before
sr.rewrite(f,null)
check(f.text.replaceAll(System.getProperty("line.separator"), "\n").trim())
//assert after.replaceAll(System.getProperty("line.separator"), "\n").trim()==f.text.replaceAll(System.getProperty("line.separator"), "\n").trim()
}
String encryptOld(str) {
def cipher = Secret.getCipher("AES");
cipher.init(Cipher.ENCRYPT_MODE, HistoricalSecrets.legacyKey);
return new String(Base64.encode(cipher.doFinal((str + HistoricalSecrets.MAGIC).getBytes("UTF-8"))))
}
String encryptNew(str) {
return Secret.fromString(str).encryptedValue
}
/**
* Directory rewrite and recursion detection
*/
@Test
void recursionDetection() {
assumeFalse("Symlinks don't work on Windows very well", Functions.isWindows())
def sw = new SecretRewriter();
def st = StreamTaskListener.fromStdout()
def o = encryptOld("Hello world")
def n = encryptNew("Hello world")
def payload = "<msg>$o</msg>"
def answer = "<msg>$n</msg>"
// set up some directories with stuff
def t = tmp.newFolder("t")
def dirs = ["a", "b", "c", "c/d", "c/d/e"]
dirs.each { p ->
def d = new File(t, p)
d.mkdir()
new File(d,"foo.xml").text = payload
}
// stuff outside
def t2 = tmp.newFolder("t2")
new File(t2,"foo.xml").text = payload
// some recursions as well as valid symlinks
new FilePath(t).child("c/symlink").symlinkTo("..",st)
new FilePath(t).child("b/symlink").symlinkTo(".",st)
new FilePath(t).child("a/symlink").symlinkTo(t2.absolutePath,st)
assert 6==sw.rewriteRecursive(t, st)
dirs.each { p->
assert new File(t,"$p/foo.xml").text.trim() ==~ MSG_PATTERN
}
// t2 is only reachable by following a symlink. this should be covered, too
assert new File(t2,"foo.xml").text.trim() ==~ MSG_PATTERN
}
}
package hudson.util;
import com.trilead.ssh2.crypto.Base64;
import hudson.FilePath;
import hudson.Functions;
import hudson.model.TaskListener;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import javax.crypto.Cipher;
import jenkins.security.ConfidentialStoreRule;
import org.apache.commons.io.FileUtils;
import static org.junit.Assert.*;
import static org.junit.Assume.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class SecretRewriterTest {
@Rule
public MockSecretRule mockSecretRule = new MockSecretRule();
@Rule
public ConfidentialStoreRule confidentialStoreRule = new ConfidentialStoreRule();
@Rule
public TemporaryFolder tmp = new TemporaryFolder();
private static final Pattern FOO_PATTERN = Pattern.compile("<foo>[{][A-Za-z0-9+/]+={0,2}[}]</foo>");
private static final Pattern MSG_PATTERN = Pattern.compile("<msg>[{][A-Za-z0-9+/]+={0,2}[}]</msg>");
private static final Pattern FOO_PATTERN2 = Pattern.compile("(<foo>[{][A-Za-z0-9+/]+={0,2}[}]</foo>){2}");
private static final Pattern ABC_FOO_PATTERN = Pattern.compile("<abc>\\s<foo>[{][A-Za-z0-9+/]+={0,2}[}]</foo>\\s</abc>");
@Test
public void singleFileRewrite() throws Exception {
String o = encryptOld("foobar"); // old
String n = encryptNew("foobar"); // new
assertTrue(FOO_PATTERN.matcher(roundtrip("<foo>" + o + "</foo>")).matches());
assertTrue(FOO_PATTERN2.matcher(roundtrip("<foo>" + o + "</foo><foo>" + o + "</foo>")).matches());
assertEquals("<foo>" + n + "</foo>", roundtrip("<foo>" + n + "</foo>"));
assertEquals("<foo>thisIsLegalBase64AndLongEnoughThatItCouldLookLikeSecret</foo>", roundtrip(" <foo>thisIsLegalBase64AndLongEnoughThatItCouldLookLikeSecret</foo> "));
// to be rewritten, it needs to be between a tag
assertEquals("<foo>" + o, roundtrip("<foo>" + o));
assertEquals(o + "</foo>", roundtrip(o + "</foo>"));
assertTrue(ABC_FOO_PATTERN.matcher(roundtrip("<abc>\n<foo>" + o + "</foo>\n</abc>")).matches());
}
private String roundtrip(String before) throws Exception {
SecretRewriter sr = new SecretRewriter(null);
File f = File.createTempFile("test", "xml", tmp.getRoot());
FileUtils.write(f, before);
sr.rewrite(f, null);
//assert after.replaceAll(System.getProperty("line.separator"), "\n").trim()==f.text.replaceAll(System.getProperty("line.separator"), "\n").trim()
return FileUtils.readFileToString(f).replaceAll(System.getProperty("line.separator"), "\n").trim();
}
private String encryptOld(String str) throws Exception {
Cipher cipher = Secret.getCipher("AES");
cipher.init(Cipher.ENCRYPT_MODE, HistoricalSecrets.getLegacyKey());
return new String(Base64.encode(cipher.doFinal((str + HistoricalSecrets.MAGIC).getBytes("UTF-8"))));
}
private String encryptNew(String str) {
return Secret.fromString(str).getEncryptedValue();
}
/**
* Directory rewrite and recursion detection
*/
@Test
public void recursionDetection() throws Exception {
assumeFalse("Symlinks don't work on Windows very well", Functions.isWindows());
SecretRewriter sw = new SecretRewriter();
TaskListener st = StreamTaskListener.fromStdout();
String o = encryptOld("Hello world");
String n = encryptNew("Hello world");
String payload = "<msg>" + o + "</msg>";
String answer = "<msg>" + n + "</msg>";
// set up some directories with stuff
File t = tmp.newFolder("t");
List<String> dirs = Arrays.asList("a", "b", "c", "c/d", "c/d/e");
for (String p : dirs) {
File d = new File(t, p);
d.mkdir();
try {
FileUtils.write(new File(d, "foo.xml"), payload);
} catch (IOException x) {
assert false : x;
}
}
// stuff outside
File t2 = tmp.newFolder("t2");
FileUtils.write(new File(t2, "foo.xml"), payload);
// some recursions as well as valid symlinks
new FilePath(t).child("c/symlink").symlinkTo("..", st);
new FilePath(t).child("b/symlink").symlinkTo(".", st);
new FilePath(t).child("a/symlink").symlinkTo(t2.getAbsolutePath(), st);
assertEquals(6, sw.rewriteRecursive(t, st));
for (String p : dirs) {
assertTrue(MSG_PATTERN.matcher(FileUtils.readFileToString(new File(t, p + "/foo.xml")).trim()).matches());
}
// t2 is only reachable by following a symlink. this should be covered, too
assertTrue(MSG_PATTERN.matcher(FileUtils.readFileToString(new File(t2, "foo.xml")).trim()).matches());
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册