Skip to content

Commit

Permalink
Merge pull request #80 from nulib/3487-reading-room-proxy
Browse files Browse the repository at this point in the history
Use the x-client-ip header for file set auth to allow proxying
  • Loading branch information
bmquinn authored Jan 23, 2023
2 parents ff443f4 + a4e012a commit 58fceef
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 4 deletions.
7 changes: 5 additions & 2 deletions src/handlers/middleware.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const {
decodeToken,
encodeToken,
ensureCharacterEncoding,
maybeUseProxiedIp,
normalizeHeaders,
objectifyCookies,
stubEventMembers,
Expand All @@ -26,20 +27,22 @@ const wrap = function (handler) {

const _processRequest = function (event) {
if (event.__processRequest) return event;
let result = stubEventMembers(event);
let result = maybeUseProxiedIp(event);
result = stubEventMembers(event);
result = normalizeHeaders(event);
result = objectifyCookies(result);
result = decodeEventBody(result);
result = decodeToken(result);
result.__processRequest = true;
if (!!process.env.DEBUG) console.log("request", result);
return result;
};

const _processResponse = function (event, response) {
let result = addCorsHeaders(event, response);
result = encodeToken(event, result);
result = ensureCharacterEncoding(result, "UTF-8");
if (process.env.DEBUG) console.log(result);
if (!!process.env.DEBUG) console.log("response", result);
return result;
};

Expand Down
10 changes: 9 additions & 1 deletion src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,17 @@ function objectifyCookies(event) {

function isFromReadingRoom(event) {
const AllowedIPs = (process.env.READING_ROOM_IPS || "").split(/\s*,\s*/);
const sourceIp = event?.requestContext?.http?.sourceIp;
const sourceIp = event.requestContext?.http?.sourceIp;
return AllowedIPs.includes(sourceIp);
}

function maybeUseProxiedIp(event) {
if (!!process.env.USE_PROXIED_IP && event.headers?.["x-client-ip"]) {
event.requestContext.http.sourceIp = event.headers["x-client-ip"];
}
return event;
}

function stubEventMembers(event) {
event.headers ||= {};
event.pathParameters ||= {};
Expand All @@ -221,6 +228,7 @@ module.exports = {
effectivePath,
ensureCharacterEncoding,
isFromReadingRoom,
maybeUseProxiedIp,
normalizeHeaders,
objectifyCookies,
stubEventMembers,
Expand Down
3 changes: 3 additions & 0 deletions template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ Resources:
Properties:
Handler: handlers/get-file-set-auth.handler
Description: Authorizes access to a file set.
Environment:
Variables:
USE_PROXIED_IP: true
Policies:
Version: 2012-10-17
Statement:
Expand Down
2 changes: 1 addition & 1 deletion test/integration/get-file-set-auth.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ describe("Authorize a file set by id", () => {
expect(result.statusCode).to.eq(204);
});

it("authorizes an restricted file set if the user is in a Reading Room", async () => {
it("authorizes a restricted file set if the user is in a Reading Room", async () => {
mock
.get("/dc-v2-file-set/_doc/1234")
.reply(200, helpers.testFixture("mocks/fileset-restricted-1234.json"));
Expand Down
33 changes: 33 additions & 0 deletions test/unit/api/helpers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const {
decodeEventBody,
decodeToken,
isFromReadingRoom,
maybeUseProxiedIp,
normalizeHeaders,
objectifyCookies,
stubEventMembers,
Expand Down Expand Up @@ -169,6 +170,38 @@ describe("helpers", () => {
});
});

describe("maybeUseProxiedIp()", () => {
it("uses the original IP if USE_PROXIED_IP is not set", () => {
const event = helpers
.mockEvent("GET", "/search")
.headers({ "x-client-ip": "123.123.123.123" })
.render();
expect(maybeUseProxiedIp(event)).to.nested.include({
"requestContext.http.sourceIp": "10.9.8.7",
});
});

it("uses the original IP if the x-client-ip header is not set", () => {
const event = helpers.mockEvent("GET", "/search").render();
process.env.USE_PROXIED_IP = "true";
expect(maybeUseProxiedIp(event)).to.nested.include({
"requestContext.http.sourceIp": "10.9.8.7",
});
});

it("uses the x-client-ip header if it is present and USE_PROXIED_IP is set", () => {
const event = helpers
.mockEvent("GET", "/search")
.headers({ "x-client-ip": "123.123.123.123" })
.render();
process.env.USE_PROXIED_IP = "true";
const subject = maybeUseProxiedIp(event);
expect(subject).to.nested.include({
"requestContext.http.sourceIp": "123.123.123.123",
});
});
});

describe("normalizeHeaders()", () => {
it("converts all headers to lowercase", () => {
const upperHeaders = ["Host", "X-Forwarded-For", "X-Forwarded-Proto"];
Expand Down

0 comments on commit 58fceef

Please sign in to comment.