_schema-version: '3.1'
ID: fpf-cf-sap-onpremise-proxy
description: On-Premise Proxy
version: 1.0.0
modules:
- name: fpf-cf-sap-onpremise-proxy-api
type: nodejs
path: proxy-api
parameters:
memory: 128M
disk-quota: 256M
requires:
- name: fpf-cf-sap-onpremise-proxy-uaa
- name: fpf-cf-sap-onpremise-proxy-conn
- name: fpf-cf-sap-onpremise-proxy-dest
resources:
- name: fpf-cf-sap-onpremise-proxy-uaa
type: org.cloudfoundry.managed-service
parameters:
service: xsuaa
service-plan: application
path: ./xs-security.json
- name: fpf-cf-sap-onpremise-proxy-conn
type: org.cloudfoundry.managed-service
parameters:
service: connectivity
service-plan: lite
- name: fpf-cf-sap-onpremise-proxy-dest
type: org.cloudfoundry.managed-service
parameters:
service: destination
service-plan: lite
const express = require("express");
const passport = require("passport");
const xssec = require("@sap/xssec");
const xsenv = require("@sap/xsenv");
const cfenv = require("cfenv");
const axios = require("axios");
const fetchToken = require("./lib/fetchToken");
const readDestination = require("./lib/readDestination");
const app = express();
const port = process.env.PORT || 3001;
passport.use("JWT", new xssec.JWTStrategy(xsenv.getServices({
uaa: {
tag: "xsuaa"
}
}).uaa));
app.use(passport.initialize());
app.use(passport.authenticate("JWT", { session: false }));
app.use(express.raw({ limit: "20MB", type: "*/*" }));
app.use("/info", (req, res) => {
res.json({
"description": "fpf-cf-sap-onpremise-proxy",
"version": "1.0.0"
});
});
app.use("/deploy/*", async (req, res) => {
try{
const urlParts = req.originalUrl.split("/");
urlParts.shift(); // remove empty element
urlParts.shift(); // remove deploy
const destinationName = urlParts.shift();
const targetUrl = "/" + urlParts.join("/");
const destCredentials = cfenv.getAppEnv().getService("fpf-cf-sap-onpremise-proxy-dest").credentials;
const connCredentials = cfenv.getAppEnv().getService("fpf-cf-sap-onpremise-proxy-conn").credentials;
const destToken = await fetchToken(destCredentials.url, destCredentials.clientid, destCredentials.clientsecret);
const destination = await readDestination(destinationName, destCredentials.uri, destToken);
const connToken = await fetchToken(connCredentials.url, connCredentials.clientid, connCredentials.clientsecret);
const reqOptions = {
method: req.method,
url: destination.destinationConfiguration.URL + targetUrl,
headers: {
"Proxy-Authorization": "Bearer " + connToken
},
proxy: {
host: connCredentials.onpremise_proxy_host,
port: connCredentials.onpremise_proxy_http_port
},
maxBodyLength: Infinity,
maxContentLength: Infinity
};
reqOptions.headers["authorization"] = `${destination.authTokens[0].type} ${destination.authTokens[0].value}`; // pre-condition: destination with credentials
["accept", "x-csrf-token", "content-type", "cookie", "accept-language", "if-match"].forEach((headerIdentifier) => {
if(req.headers[headerIdentifier]) {
reqOptions.headers[headerIdentifier] = req.headers[headerIdentifier];
}
});
if(req.method !== "GET" && req.method !== "DELETE" && req.body) {
reqOptions.data = Buffer.from(req.body).toString("utf-8");
}
reqOptions.validateStatus = (status) => {
return status < 999;
};
const resOnPrem = await axios(reqOptions);
res.status(resOnPrem.status).set(resOnPrem.headers).send(resOnPrem.data);
} catch (error) {
console.log(error);
res.status(500).send(error);
}
});
app.listen(port, () => {
console.log(`Proxy listening on port ${port}`);
});
const axios = require("axios");
const tokenCache = [];
module.exports = async (oauthUrl, oauthClient, oauthSecret) => {
const tokenIdx = tokenCache.findIndex((cacheEntry) => {
return cacheEntry.oauthUrl === oauthUrl && cacheEntry.oauthClient === oauthClient;
})
if(tokenIdx !== -1) {
const cachedToken = tokenCache[tokenIdx];
if(Math.abs((new Date().getTime() - cachedToken.created.getTime()) / 1000) > 180) {
tokenCache.splice(tokenIdx, 1);
} else {
return cachedToken.token;
}
}
const tokenUrl = oauthUrl + "/oauth/token?grant_type=client_credentials&response_type=token";
const config = {
headers: {
Authorization: "Basic " + Buffer.from(oauthClient + ':' + oauthSecret).toString("base64")
}
};
const res = await axios.get(tokenUrl, config);
const access_token = res.data.access_token;
tokenCache.push({
token: access_token,
oauthUrl: oauthUrl,
oauthClient: oauthClient,
created: new Date()
});
return access_token;
}
const axios = require("axios");
module.exports = async (destinationName, destUri, token) => {
const destSrvUrl =
destUri + "/destination-configuration/v1/destinations/" + destinationName;
const config = {
headers: {
Authorization: "Bearer " + token,
},
};
const res = await axios.get(destSrvUrl, config);
return res.data;
};
{
"cwd": "./dist",
"files": "**/*.*",
"server": "https://e58fa57dtrial-dev-fpf-cf-sap-onpremise-proxy-api.cfapps.eu10.hana.ondemand.com/deploy/deva4h",
"client": "001",
"language": "EN",
"package": "ZZ_UI5_REPOSITORY",
"bspContainer": "ZZ_UI5_TEST_BB",
"bspContainerText": "Test UI5 Deployment from Bitbucket",
"createTransport": true,
"transportText": "Test Transport Deployment from Bitbucket",
"transportUseLocked": true,
"calculateApplicationIndex": true
}
"scripts": {
"deploy": "ui5-deployer deploy --config .ui5deployrc"
}
image: node:14
pipelines:
branches:
master:
# deployments steps
- step:
name: 'Deployment to ABAP development system'
deployment: abap_dev
script:
- apt-get update
- apt-get install -y jq
- cd packages/ui5-test-app
- npm ci
- cf_token=$(curl -X POST https://e58fa57dtrial.authentication.eu10.hana.ondemand.com/oauth/token -H 'application/x-www-form-urlencoded' -d "client_id=$cf_clientid" -d "client_secret=$cf_clientsecret" -d 'grant_type=client_credentials' | jq -r '.access_token')
- npm run build
- npm run deploy -- --bearerToken $cf_token
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
5 | |
5 | |
5 | |
5 | |
4 | |
4 | |
4 | |
4 | |
3 | |
3 |