Skip to content

Commit

Permalink
When rotating, don't retry 403s (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
seamusabshere authored Oct 14, 2020
1 parent 5ad8b22 commit e2878b8
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 135 deletions.
44 changes: 35 additions & 9 deletions prepare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,33 +141,59 @@ export default function prepare(
VAULT_ADDR
);

class RetryAuthFailure extends Error {}

function checkStatusCode(response: Response) {
if (response.statusCode == 403) {
throw new RetryAuthFailure(
"vault responded with 403 access denied when i tried to rotate, giving up"
);
} else {
return response;
}
}

function getNewLease(vaultPath: string, sync: boolean) {
const req = sync ? request : asyncRequest;
const fullUrl = VAULT_ADDR + VAULT_API_VERSION + "/" + vaultPath;
const response = req("GET", fullUrl, {
headers: {
"X-Vault-Token": VAULT_TOKEN,
},
});
if (sync) {
onLease(vaultPath, parseLeaseResponse(response));
const response = request("GET", fullUrl, {
headers: {
"X-Vault-Token": VAULT_TOKEN,
},
});
try {
onLease(vaultPath, parseLeaseResponse(checkStatusCode(response)));
} catch (e) {
console.error(e.message);
if (!(e instanceof RetryAuthFailure)) {
throw e;
}
}
} else {
const response = asyncRequest("GET", fullUrl, {
headers: {
"X-Vault-Token": VAULT_TOKEN,
},
});
!options.silent &&
console.log(
logPrefix +
"rotating lease for " +
Object.keys(secretsByPath[vaultPath]).join(", ")
);
Promise.resolve(response)
.then(checkStatusCode)
.then(parseLeaseResponse)
.then(onLease.bind(null, vaultPath))
.catch(function retry(err: { stack?: string }) {
console.error(
logPrefix + "ERROR trying to rotate lease " + vaultPath
);
console.error(logPrefix + (err && err.stack ? err.stack : err));
console.error("retrying in 1s");
setTimeout(getNewLease.bind(null, vaultPath), 1000);
if (!(err instanceof RetryAuthFailure)) {
console.error("retrying in 1s");
setTimeout(getNewLease.bind(null, vaultPath), 1000);
}
});
}
}
Expand Down
257 changes: 131 additions & 126 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,143 +95,148 @@ function test(name: string, options: TestOptions) {
});
}

test("one env var", {
secretfile: "thing secret/thing:url",
secrets: {
"secret/thing": {
url: "hellooooo",
},
},
expected: {
thing: "hellooooo",
},
});
describe("vault-env", function () {
// up from 2
this.timeout(5000);

test("one env var", {
secretfile: "thing secret/thing:url",
secrets: {
"secret/thing": {
url: "hellooooo",
},
},
expected: {
thing: "hellooooo",
},
});

test("override env var", {
secretfile: "thing secret/thing:url",
secrets: {},
expected: {
thing: "hellooooo",
},
overrides: {
thing: "hellooooo",
},
});
test("override env var", {
secretfile: "thing secret/thing:url",
secrets: {},
expected: {
thing: "hellooooo",
},
overrides: {
thing: "hellooooo",
},
});

test("two env vars", {
secretfile: "thing1 secret/thing:url1\nthing2 secret/thing:url2",
secrets: {
"secret/thing": {
url1: "hellooooo",
url2: "goodbyeeee",
},
},
expected: {
thing1: "hellooooo",
thing2: "goodbyeeee",
},
});
test("two env vars", {
secretfile: "thing1 secret/thing:url1\nthing2 secret/thing:url2",
secrets: {
"secret/thing": {
url1: "hellooooo",
url2: "goodbyeeee",
},
},
expected: {
thing1: "hellooooo",
thing2: "goodbyeeee",
},
});

test("one invalid env var", {
secretfile: "2 secret/thing:url1",
secrets: {},
throws: /Error parsing Secretfile:\nInvalid line 1: 2 secret\/thing:url1/,
});
test("one invalid env var", {
secretfile: "2 secret/thing:url1",
secrets: {},
throws: /Error parsing Secretfile:\nInvalid line 1: 2 secret\/thing:url1/,
});

test("two invalid env vars", {
secretfile: "2 secret/thing:url1\n3 boop:thing",
secrets: {},
throws: /Error parsing Secretfile:\nInvalid line 1: 2 secret\/thing:url1\nInvalid line 2: 3 boop:thing/,
});
test("two invalid env vars", {
secretfile: "2 secret/thing:url1\n3 boop:thing",
secrets: {},
throws: /Error parsing Secretfile:\nInvalid line 1: 2 secret\/thing:url1\nInvalid line 2: 3 boop:thing/,
});

test("missing secret", {
secretfile: "boop secret/thing:url",
secrets: {},
throws: /key not found/,
});
test("missing secret", {
secretfile: "boop secret/thing:url",
secrets: {},
throws: /key not found/,
});

test("missing environment variable secret", {
secretfile: "boop secret/$MISSING_VAR:url",
secrets: {},
throws: /Error parsing Secretfile:\nMissing from environment: MISSING_VAR for line 1 boop secret\/\$MISSING_VAR:url/,
});
test("missing environment variable secret", {
secretfile: "boop secret/$MISSING_VAR:url",
secrets: {},
throws: /Error parsing Secretfile:\nMissing from environment: MISSING_VAR for line 1 boop secret\/\$MISSING_VAR:url/,
});

test("one invalid secret path", {
secretfile: "thing secret/thing",
secrets: {},
throws: /Error parsing Secretfile/,
});
test("one invalid secret path", {
secretfile: "thing secret/thing",
secrets: {},
throws: /Error parsing Secretfile/,
});

test("two invalid secret paths", {
secretfile: "thing secrets/thing\nstuff secrets/stuff",
secrets: {},
throws: /Error parsing Secretfile/,
});
test("two invalid secret paths", {
secretfile: "thing secrets/thing\nstuff secrets/stuff",
secrets: {},
throws: /Error parsing Secretfile/,
});

test("multiple secrets from one path", {
secretfile: "one secrets/test:one\ntwo secrets/test:two",
secrets: {
"secrets/test": { one: "one", two: "two" },
},
expected: {
one: "one",
two: "two",
},
});
test("multiple secrets from one path", {
secretfile: "one secrets/test:one\ntwo secrets/test:two",
secrets: {
"secrets/test": { one: "one", two: "two" },
},
expected: {
one: "one",
two: "two",
},
});

test("env substitution", {
secretfile: "one secrets/$SAMPLE:one\ntwo secrets/${SAMPLE}:two",
secrets: {
"secrets/hello": { one: "one", two: "two" },
},
expected: {
one: "one",
two: "two",
},
});
test("env substitution", {
secretfile: "one secrets/$SAMPLE:one\ntwo secrets/${SAMPLE}:two",
secrets: {
"secrets/hello": { one: "one", two: "two" },
},
expected: {
one: "one",
two: "two",
},
});

test("one var local only", {
secretfile: "thing secret/thing:url",
secrets: {
"secret/thing": {
url: "hellooooo",
},
},
expected: {
thing: "hellooooo",
},
local: true,
});
test("one var local only", {
secretfile: "thing secret/thing:url",
secrets: {
"secret/thing": {
url: "hellooooo",
},
},
expected: {
thing: "hellooooo",
},
local: true,
});

test("two vars local only", {
secretfile: "thing1 secret/thing:url1\nthing2 secret/thing:url2",
secrets: {
"secret/thing": {
url1: "hellooooo",
url2: "goodbyeeee",
},
},
expected: {
thing1: "hellooooo",
thing2: "goodbyeeee",
},
local: true,
});
test("two vars local only", {
secretfile: "thing1 secret/thing:url1\nthing2 secret/thing:url2",
secrets: {
"secret/thing": {
url1: "hellooooo",
url2: "goodbyeeee",
},
},
expected: {
thing1: "hellooooo",
thing2: "goodbyeeee",
},
local: true,
});

test("passing in data", {
secretdata: {
thing1: { vaultPath: "secret/thing", vaultProp: "url1" },
thing2: { vaultPath: "secret/thing", vaultProp: "url2" },
},
secrets: {
"secret/thing": {
url1: "hellooooo",
url2: "goodbyeeee",
},
},
expected: {
thing1: "hellooooo",
thing2: "goodbyeeee",
},
local: true,
test("passing in data", {
secretdata: {
thing1: { vaultPath: "secret/thing", vaultProp: "url1" },
thing2: { vaultPath: "secret/thing", vaultProp: "url2" },
},
secrets: {
"secret/thing": {
url1: "hellooooo",
url2: "goodbyeeee",
},
},
expected: {
thing1: "hellooooo",
thing2: "goodbyeeee",
},
local: true,
});
});

0 comments on commit e2878b8

Please sign in to comment.