Skip to content

Commit

Permalink
Update Docspace reverse proxy (#1)
Browse files Browse the repository at this point in the history
Co-authored-by: Yaroslav Pshenichnikov <yaroslav.pshenichnikov@onlyoffice.com>
Co-authored-by: Alexey Bannov <alexey.bannov@onlyoffice.com>
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/docspace_reverse_proxy/pulls/1
  • Loading branch information
3 people committed Sep 5, 2024
1 parent 14860f9 commit af906f4
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 24 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/sam-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
export DYNAMODB_TABLE_NAME="${{ secrets.MAIN_DYNAMODB_TABLE_NAME }}"
fi
sed -i "s/dynamodb_table_name_placeholder/${DYNAMODB_TABLE_NAME}/g" ./docspace-reverse-proxy/index.mjs
sed -i "s/dynamodb_table_name_placeholder/${DYNAMODB_TABLE_NAME}/g" ./zoom-reverse-proxy/index.mjs
- name: Set viewer request domain name variable
run: |
Expand All @@ -52,6 +53,7 @@ jobs:
fi
awk -v rmap="$(<regions_map.tmp)" '{ gsub(/regionsMap_placeholder/, rmap); print; }' ./docspace-reverse-proxy/index.mjs > temp_index.mjs && mv temp_index.mjs ./docspace-reverse-proxy/index.mjs
awk -v rmap="$(<ddb_regions_map.tmp)" '{ gsub(/ddbRegionsMap_placeholder/, rmap); print; }' ./docspace-reverse-proxy/index.mjs > temp_index.mjs && mv temp_index.mjs ./docspace-reverse-proxy/index.mjs
awk -v rmap="$(<ddb_regions_map.tmp)" '{ gsub(/ddbRegionsMap_placeholder/, rmap); print; }' ./zoom-reverse-proxy/index.mjs > temp_index.mjs && mv temp_index.mjs ./zoom-reverse-proxy/index.mjs
# Build and deploy stack
- run: sam build -u --template-file ${GITHUB_REF_NAME}-template.yaml
Expand Down
32 changes: 28 additions & 4 deletions develop-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ Resources:
Properties:
CodeUri: docspace-reverse-proxy/
Description: ""
MemorySize: 256
MemorySize: 512
Timeout: 3
Handler: index.handler
Runtime: nodejs18.x
Runtime: nodejs20.x
Architectures:
- x86_64
EventInvokeConfig:
Expand All @@ -39,7 +39,30 @@ Resources:
MemorySize: 128
Timeout: 3
Handler: index.handler
Runtime: nodejs18.x
Runtime: nodejs20.x
Architectures:
- x86_64
EventInvokeConfig:
MaximumEventAgeInSeconds: 21600
MaximumRetryAttempts: 2
EphemeralStorage:
Size: 512
RuntimeManagementConfig:
UpdateRuntimeOn: Auto
SnapStart:
ApplyOn: None
PackageType: Zip
Role: !GetAtt DocspaceReverseProxyRole.Arn

zoomreverseproxy:
Type: AWS::Serverless::Function
Properties:
CodeUri: zoom-reverse-proxy/
Description: ""
MemorySize: 128
Timeout: 3
Handler: index.handler
Runtime: nodejs20.x
Architectures:
- x86_64
EventInvokeConfig:
Expand Down Expand Up @@ -130,12 +153,13 @@ Resources:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- cloudwatch:PutMetricData
Resource: "*"

DyanmoDBFullAccessPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
Description: Allows functions to write logs
Description: Set dynamodb permissions
Roles:
- !Ref DocspaceReverseProxyRole
PolicyDocument:
Expand Down
66 changes: 48 additions & 18 deletions docspace-reverse-proxy/index.mjs
Original file line number Diff line number Diff line change
@@ -1,47 +1,77 @@
'use strict';

import { DynamoDBClient, GetItemCommand } from "@aws-sdk/client-dynamodb";

const DEBUG_MODE_ON = true;

if (!DEBUG_MODE_ON) {
console = console || {};
console.log = function(){};
}

const cachedItem = {};

const regionsMap = {
regionsMap_placeholder
regionsMap_placeholder
};

const ddbRegionsMap = {
ddbRegionsMap_placeholder
ddbRegionsMap_placeholder
};

const dynamodbTableName = "dynamodb_table_name_placeholder";

const execRegionCode = process.env.AWS_REGION;
const execAWSRegion = process.env.AWS_REGION;

var ddbClientRegion = ddbRegionsMap["default"];

if (ddbRegionsMap[execRegionCode]) {
ddbClientRegion = ddbRegionsMap[execRegionCode];
if (ddbRegionsMap[execAWSRegion]) {
ddbClientRegion = ddbRegionsMap[execAWSRegion];

console.log("change ddbClient region from %s to %s", ddbRegionsMap["default"], ddbClientRegion);
}

import { DynamoDBClient, GetItemCommand } from "@aws-sdk/client-dynamodb";
var ddbClient = null;
var ddbClientDefault = null;

async function getTenantRegion(ddbRegion, tenantDomain) {
function getDynamoDBClient(ddbRegion) {

if (ddbRegion == ddbRegionsMap["default"]) {
if (ddbClientDefault == null) {
ddbClientDefault = new DynamoDBClient({ region: ddbRegionsMap["default"] });
}

return ddbClientDefault;
} else {
if (ddbClient == null) {
ddbClient = new DynamoDBClient({ region: ddbRegion });
}

return ddbClient;
}
}

console.log("getTenantRegion params ddbRegion: %s, tenantDomain: %s", ddbRegion, tenantDomain);

const ddbClient = new DynamoDBClient({ region: ddbRegion });
async function getTenantRegion(ddbRegion, tenantDomain) {
console.log("getTenantRegion params ddbRegion: %s, tenantDomain: %s", ddbRegion, tenantDomain);

const getItemParams = {
Key: {
'tenant_domain': { S: tenantDomain }
"tenant_domain": { S: tenantDomain }
},
ProjectionExpression: "tenant_region",
TableName: dynamodbTableName
};

console.log("[DynamoDb] before send command get item %s with tenant domain %s", JSON.stringify(getItemParams), tenantDomain);
console.log(`[DynamoDb] before send GetItemCommand ${JSON.stringify(getItemParams)} with tenant domain ${tenantDomain}`);

const start = Date.now();

const response = await getDynamoDBClient(ddbRegion).send(new GetItemCommand(getItemParams));

const response = await ddbClient.send(new GetItemCommand(getItemParams));
const end = Date.now();

console.log("[DynamoDb] responce send command get item %s with tenant domain %s", JSON.stringify(response), tenantDomain);
console.log(`[DynamoDb] after send GetItemCommand ${JSON.stringify(response)} with tenant domain ${tenantDomain}. Execution time: ${end - start} `);

if (response && response.Item) {

Expand Down Expand Up @@ -74,17 +104,17 @@ export const handler = async (event, context, callback) => {

if (request.uri.toLowerCase() == "/apisystem/portal/register" && request.method == "POST") {
console.log("START: Register portal request");

console.log("Register portal request body %s", request.body);

let body = JSON.parse(Buffer.from(request.body.data, 'base64').toString('utf8'));
let regionFromRequest = body["awsRegion"];
let portalName = body["portalName"];

if(regionFromRequest !== null && regionFromRequest !== '' && regionFromRequest!==undefined) {
regionFromRequest = regionFromRequest.toLowerCase();
}


originDomain = regionsMap[regionFromRequest];

console.log("Register portal request: Origin Domain is %s, awsRegion is %s", originDomain, regionFromRequest);
Expand Down Expand Up @@ -112,7 +142,7 @@ export const handler = async (event, context, callback) => {
console.log("Register portal request: Change request origin to %s", originDomain);
}

console.log("request after changed %s", JSON.stringify(request));
console.log("request after changed %s", JSON.stringify(request));

console.log("END: Register portal request");

Expand Down
4 changes: 2 additions & 2 deletions main-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ Resources:
Properties:
CodeUri: docspace-reverse-proxy/
Description: ""
MemorySize: 256
MemorySize: 512
Timeout: 3
Handler: index.handler
Runtime: nodejs18.x
Runtime: nodejs20.x
Architectures:
- x86_64
EventInvokeConfig:
Expand Down
84 changes: 84 additions & 0 deletions zoom-reverse-proxy/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
'use strict';

const cachedItem = {};
const regionsMap = {
regionsMap_placeholder
};

const ddbRegionsMap = {
ddbRegionsMap_placeholder
};

const dynamodbTableName = "dynamodb_table_name_placeholder";

const execRegionCode = process.env.AWS_REGION;

var ddbClientRegion = ddbRegionsMap["default"];

if (ddbRegionsMap[execRegionCode]) {
ddbClientRegion = ddbRegionsMap[execRegionCode];

console.log("change ddbClient region from %s to %s", ddbRegionsMap["default"], ddbClientRegion);
}

console.log("DynamoDB client region set to: %s", ddbClientRegion);

import { DynamoDBClient, GetItemCommand } from "@aws-sdk/client-dynamodb";

async function getTenantRegion(ddbRegion, tenantDomain) {
console.log("Fetching tenant region for domain: %s from DynamoDB region: %s", tenantDomain, ddbRegion);
const ddbClient = new DynamoDBClient({ region: ddbRegion });
const getItemParams = {
Key: { 'tenant_domain': { S: tenantDomain } },
ProjectionExpression: "tenant_region",
TableName: dynamodbTableName
};

try {
const response = await ddbClient.send(new GetItemCommand(getItemParams));
if (response.Item) {
const tenantRegion = regionsMap[response.Item["tenant_region"]["S"]];
console.log("Tenant region fetched: %s", tenantRegion);
return tenantRegion;
} else {
console.warn("No data found for domain: %s", tenantDomain);
return null;
}
} catch (err) {
console.error("Error fetching from DynamoDB: %s", err);
return null;
}
}

export async function handler(event) {
const request = event.Records[0].cf.request;
const headers = request.headers;
const fullDomain = headers.host[0].value.toLowerCase();
const domainParts = fullDomain.split('.');

if (domainParts.length === 4 && domainParts[1] === 'devops' && domainParts[2] === 'onlyoffice' && domainParts[3] === 'io') {
const tenantDomain = fullDomain;

// Check the cache first
if (cachedItem[tenantDomain] && cachedItem[tenantDomain].expiresOn > Date.now()) {
request.origin.custom.domainName = cachedItem[tenantDomain].value;
console.log("Origin fetched from cache for domain: %s", tenantDomain);
} else {
// Fetch the region from DynamoDB and update the origin
const tenantRegion = await getTenantRegion(ddbClientRegion, tenantDomain);
if (tenantRegion) {
request.origin.custom.domainName = tenantRegion;
cachedItem[tenantDomain] = {
value: tenantRegion,
expiresOn: Date.now() + 15 * 60 * 1000 // Cache for 15 minutes
};
console.log("Origin updated to %s for domain: %s", tenantRegion, tenantDomain);
} else {
request.origin.custom.domainName = regionsMap["default"];
console.log("Default origin (%s) used for domain: %s", regionsMap["default"], tenantDomain);
}
}
}

return request;
}

0 comments on commit af906f4

Please sign in to comment.