@sap-cloud-sdk/core
Version:
SAP Cloud SDK for JavaScript core
315 lines • 13.9 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnvironmentAccessor = exports.extractClientCredentials = exports.resolveService = exports.getXsuaaServiceCredentials = exports.getDestinationServiceUri = exports.getEnvironmentVariable = exports.getVcapService = exports.getDestinationService = exports.getService = exports.getServiceList = exports.getServiceCredentialsList = exports.getDestinationServiceCredentialsList = exports.getDestinationServiceCredentials = exports.getDestinationBasicCredentials = void 0;
var util_1 = require("@sap-cloud-sdk/util");
var xsenv = __importStar(require("@sap/xsenv"));
var jwt_1 = require("./jwt");
var logger = (0, util_1.createLogger)({
package: 'core',
messageContext: 'environment-accessor'
});
/**
* Basic Credentials Getter from Destination service credentials needed for JWT generator.
*
* @returns Basic credentials.
*/
function getDestinationBasicCredentials() {
var destinationCredentials = getDestinationServiceCredentials();
var basicCredentials = {
clientid: destinationCredentials.clientid
? destinationCredentials.clientid
: null,
clientsecret: destinationCredentials.clientsecret
? destinationCredentials.clientsecret
: null
};
return basicCredentials;
}
exports.getDestinationBasicCredentials = getDestinationBasicCredentials;
/**
* First 'destination' credentials getter.
*
* @returns The 'destination' credentials object or `null`, if it does not exist.
*/
function getDestinationServiceCredentials() {
return (0, util_1.first)(getDestinationServiceCredentialsList());
}
exports.getDestinationServiceCredentials = getDestinationServiceCredentials;
/**
* Destination credentials getter.
*
* @returns A list of 'credentials' objects in 'destination' service.
*/
function getDestinationServiceCredentialsList() {
return getServiceList('destination').map(function (s) { return s.credentials; });
}
exports.getDestinationServiceCredentialsList = getDestinationServiceCredentialsList;
/**
* Credentials list getter for a given service.
* @param service - Service name
* @returns Fetched credentials objects of existing service in 'VCAP_SERVICES'.
*/
function getServiceCredentialsList(service) {
var credentials = [];
getServiceList(service).forEach(function (entry) {
if ('credentials' in entry) {
credentials.push(entry['credentials']);
}
else {
logger.warn("Skipping a service in ".concat(service, ". Object has no 'credentials'."));
}
});
return credentials;
}
exports.getServiceCredentialsList = getServiceCredentialsList;
/**
* Services getter for a given service.
* @param service - Service name.
* @returns List of service bindings of the given type. Returns an empty array if no service binding exists for the given type.
*/
function getServiceList(service) {
return xsenv.filterServices({ label: service }); // TODO: how do we allow propagating custom secret paths for k8s?
}
exports.getServiceList = getServiceList;
/**
* Returns the first found instance for the given service type.
* @param service - The service type.
* @returns The first found service.
*/
function getService(service) {
var services = xsenv.filterServices({ label: service });
if (!services.length) {
logger.warn("No services of type ".concat(service, " found! This might cause errors in other parts of the application."));
return undefined;
}
if (services.length > 1) {
logger.warn("Found more than one service instance for service type ".concat(service, ". Found: ").concat(services
.map(function (s) { return s.name; })
.join(', '), ". Selecting the first one."));
}
return services[0];
}
exports.getService = getService;
/**
* Get destination service if one is present.
*
* @returns Destination service
* @throws Error in case no destination service is found in the VCAP variables
*/
function getDestinationService() {
var destinationService = getService('destination');
if (!destinationService) {
throw Error('No binding to a destination service found.');
}
return destinationService;
}
exports.getDestinationService = getDestinationService;
/**
* 'VCAP_SERVICES' Getter from environment variables.
* This function returns the VCAP_SERVICES as object or `null`, if it is not defined (i.e. no services are bound to the application).
*
* @returns 'VCAP_SERVICES' found in environment variables or `null`, if not defined. The key denotes the name ov the service and the value is the definition.
*/
function getVcapService() {
var env = getEnvironmentVariable('VCAP_SERVICES');
var vcapServices;
if (!env) {
logger.warn("Environment variable 'VCAP_SERVICES' is not defined.");
return null;
}
try {
vcapServices = JSON.parse(env);
}
catch (error) {
throw new util_1.ErrorWithCause("Failed to parse environment variable 'VCAP_SERVICES'.", error);
}
if (!Object.keys(vcapServices).length) {
throw new Error("Environment variable 'VCAP_SERVICES' is defined but empty. This should not happen.");
}
return vcapServices;
}
exports.getVcapService = getVcapService;
/**
* Environment variables accessor.
* @param name - Environment variable name.
* @returns Env variable value if defined.
* null: If not defined.
*/
function getEnvironmentVariable(name) {
if (process.env[name]) {
return process.env[name];
}
logger.info('Environment variable ' + name + ' is not defined.');
return null;
}
exports.getEnvironmentVariable = getEnvironmentVariable;
/**
* Destination URI getter
* NOTICE: If there exist more than one destination/uri, the function
* returns the first entry.
*
* @returns The first existing uri in destination or `null`, if not found.
*/
function getDestinationServiceUri() {
var destinationServiceCredentials = getDestinationServiceCredentialsList();
var uris = [];
for (var _i = 0, destinationServiceCredentials_1 = destinationServiceCredentials; _i < destinationServiceCredentials_1.length; _i++) {
var credential = destinationServiceCredentials_1[_i];
if ('uri' in credential) {
uris.push(credential['uri']);
}
else {
logger.info("Skipping credentials in 'destination'. 'uri' property not defined");
}
}
return uris[0] || null;
}
exports.getDestinationServiceUri = getDestinationServiceUri;
/**
* Takes a decoded JWT and uses the client_id and audience claims to determine the XSUAA service instance
* that issued the JWT. Returns the credentials if a match is found, otherwise throws an error.
* If no decoded JWT is specified, then returns the first existing XSUAA credential service plan "application".
* @param token - Either an encoded or decoded JWT.
* @returns The credentials for a match, otherwise `null`.
*/
function getXsuaaServiceCredentials(token) {
return typeof token === 'string'
? selectXsuaaInstance((0, jwt_1.decodeJwt)(token))
: selectXsuaaInstance(token);
}
exports.getXsuaaServiceCredentials = getXsuaaServiceCredentials;
/**
* Takes a string that represents the service type and resolves it by calling [[getService]].
* If the parameter is already an instance of [[Service]], it is returned directly.
*
* Throws an error when no service can be found for the given type.
* @param service - A string representing the service type or a [[Service]] instance.
* @returns A [[Service]] instance.
*/
function resolveService(service) {
if (typeof service === 'string') {
var serviceInstance = getService(service);
if (!serviceInstance) {
throw Error("Unable to get access token for \"".concat(service, "\" service. No service instance of type \"").concat(service, "\" found."));
}
return serviceInstance;
}
return service;
}
exports.resolveService = resolveService;
/**
* Extracts the credentials of a service into an instance of [[ClientCredentials]].
* @param serviceCreds - The credentials of a service as read from VCAP_SERVICES.
* @returns A [[ClientCredentials]] instance.
*/
function extractClientCredentials(serviceCreds) {
if (!serviceCreds.clientsecret) {
throw new Error("Cloud not extract client secret for clientId: ".concat(serviceCreds.clientid, "."));
}
return {
username: serviceCreds.clientid,
password: serviceCreds.clientsecret
};
}
exports.extractClientCredentials = extractClientCredentials;
function selectXsuaaInstance(token) {
var xsuaaCredentials = getServiceList('xsuaa').map(function (service) { return service.credentials; });
if (!arrayHasAtLeastOneElement(xsuaaCredentials)) {
throw Error('No binding to an XSUAA service instance found. Please make sure to bind an instance of the XSUAA service to your application.');
}
return token
? selectXsuaaInstanceWithJwt(xsuaaCredentials, token)
: selectXsuaaInstanceWithoutJwt(xsuaaCredentials);
}
function handleOneXsuuaInstance(xsuaaCredentials) {
logger.debug("Only one XSUAA instance bound. This one is used: ".concat(xsuaaCredentials[0].xsappname));
return xsuaaCredentials[0];
}
function arrayHasAtLeastOneElement(array) {
return !!array.length && array.length > 0;
}
function arrayHasExactlyOneElement(array) {
return array.length === 1;
}
function selectXsuaaInstanceWithoutJwt(xsuaaCredentials) {
if (!arrayHasExactlyOneElement(xsuaaCredentials)) {
logger.warn("The following XSUAA instances are bound: ".concat(xsuaaCredentials.map(function (x) { return "\n\t- ".concat(x.xsappname); }), "\n No JWT given to select XSUAA instance. ").concat(choseFirstOneText(xsuaaCredentials)));
return xsuaaCredentials[0];
}
return handleOneXsuuaInstance(xsuaaCredentials);
}
function selectXsuaaInstanceWithJwt(xsuaaCredentials, jwt) {
var selectedAll = __spreadArray(__spreadArray([], matchingClientId(xsuaaCredentials, jwt), true), matchingAudience(xsuaaCredentials, jwt), true);
var selectedUnique = (0, util_1.unique)(selectedAll.map(function (x) { return x.clientid; })).map(function (id) { return selectedAll.find(function (y) { return y.clientid === id; }); });
if (selectedUnique.length === 1) {
logger.debug("One XSUAA instance found using JWT in service binding. Used service name is: ".concat(xsuaaCredentials[0].xsappname));
return xsuaaCredentials[0];
}
if (selectedUnique.length > 1) {
logger.warn("Multiple XSUAA instances could be matched to the given JWT: ".concat(xsuaaCredentials.map(function (x) { return "\n\t- ".concat(x.xsappname); }), "\n ").concat(choseFirstOneText(xsuaaCredentials)));
return selectedUnique[0];
}
if (!arrayHasExactlyOneElement(xsuaaCredentials)) {
logger.warn("Multiple XSUAA instances found: ".concat(xsuaaCredentials.map(function (x) { return "\n\t- ".concat(x.xsappname); }), "\n None of those match either client id or audience from the given JWT. ").concat(choseFirstOneText(xsuaaCredentials)));
return xsuaaCredentials[0];
}
return handleOneXsuuaInstance(xsuaaCredentials);
}
function choseFirstOneText(xsuaaCredentials) {
return "Choosing the first one (xsappname: \"".concat((0, util_1.first)(xsuaaCredentials).xsappname, "\").");
}
function matchingClientId(xsuaaCredentials, token) {
return xsuaaCredentials.filter(function (credentials) { return credentials.clientid === token.client_id; });
}
function matchingAudience(xsuaaCredentials, token) {
return xsuaaCredentials.filter(function (credentials) {
return (0, jwt_1.audiences)(token).has(credentials.xsappname);
});
}
/**
* @deprecated Since v1.5.0. Use directly exported functions instead
*/
exports.EnvironmentAccessor = {
getDestinationBasicCredentials: getDestinationBasicCredentials,
getDestinationServiceCredentials: getDestinationServiceCredentials,
getDestinationServiceCredentialsList: getDestinationServiceCredentialsList,
getServiceCredentialsList: getServiceCredentialsList,
getServiceList: getServiceList,
getVcapService: getVcapService,
getEnvironmentVariable: getEnvironmentVariable,
getDestinationServiceUri: getDestinationServiceUri,
getXsuaaServiceCredentials: getXsuaaServiceCredentials
};
//# sourceMappingURL=environment-accessor.js.map
;