UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

234 lines (232 loc) 10.1 kB
import { of } from 'rxjs'; import { map, mergeMap } from 'rxjs/operators'; import { SmeWebTelemetry } from '../diagnostics/sme-web-telemetry'; import { EnvironmentModule } from '../manifest/environment-modules'; import { GatewayUrlTranslator } from './gateway-url-translator'; import { headerConstants } from './http-constants'; import { Net } from './net'; /** * Node Cim output type. */ export var NodeCimOutput; (function (NodeCimOutput) { /** * Single instance. */ NodeCimOutput[NodeCimOutput["Single"] = 0] = "Single"; /** * Multiple instances. */ NodeCimOutput[NodeCimOutput["Multiple"] = 1] = "Multiple"; /** * Invoke result. */ NodeCimOutput[NodeCimOutput["Result"] = 2] = "Result"; /** * WQL query result. */ NodeCimOutput[NodeCimOutput["Query"] = 3] = "Query"; })(NodeCimOutput || (NodeCimOutput = {})); /** * The Node Connection class for creating requests and calling the Gateway's Node API */ export class NodeConnection { gateway; authorizationManager; /** * Initializes a new instance of the GatewayService class. * * @param gateway the gateway Connection * @param authorizationManager the authorization manager. */ constructor(gateway, authorizationManager) { this.gateway = gateway; this.authorizationManager = authorizationManager; } post(nodeOrService, remained, body, request) { const { nodeName, relativeUrl } = this.getNodeUrl(nodeOrService, remained); request = this.createNodeRequest(request || {}, nodeName); return this.gateway.post(relativeUrl, body, request); } get(nodeOrService, remained, request) { const { nodeName, relativeUrl } = this.getNodeUrl(nodeOrService, remained); request = this.createNodeRequest(request || {}, nodeName); return this.gateway.get(relativeUrl, request); } put(nodeOrService, remained, body, request) { const { nodeName, relativeUrl } = this.getNodeUrl(nodeOrService, remained); request = this.createNodeRequest(request || {}, nodeName); return this.gateway.put(relativeUrl, body, request); } patch(nodeOrService, remained, body, request) { const { nodeName, relativeUrl } = this.getNodeUrl(nodeOrService, remained); request = this.createNodeRequest(request || {}, nodeName); return this.gateway.patch(relativeUrl, body, request); } delete(nodeOrService, remained, body, request) { const { nodeName, relativeUrl } = this.getNodeUrl(nodeOrService, remained); request = this.createNodeRequest(request || {}, nodeName); return this.gateway.delete(relativeUrl, body, request); } deleteQuick(nodeOrService, remained, request) { const { nodeName, relativeUrl } = this.getNodeUrl(nodeOrService, remained); request.headers = request.headers || {}; if (!request.authToken) { // if we don't have an authToken, then make sure we are not waiting on one. this.authorizationManager.addAuthorizationRequestHeader(request, nodeName); } else { this.authorizationManager.addAuthorizationRequestHeader(request, nodeName, request.authToken); } const endpoint = this.authorizationManager.getJeaEndpoint(nodeName); if (request.powerShellEndpoint) { // Override JEA fallback if endpoint is explicitly set for debugging purposes request.headers[headerConstants.POWERSHELL_ENDPOINT] = request.powerShellEndpoint; } else if (endpoint) { request.headers[headerConstants.POWERSHELL_ENDPOINT] = endpoint; } if (request.authenticationMechanism === 'Credssp') { request.headers[headerConstants.AUTHENTICATION_MECHANISM] = request.authenticationMechanism; } return this.gateway.deleteQuick(relativeUrl, request.headers); } /** * Persists the JEA powershell endpoint context * @param nodeName The node name * @param endpoint The powershell endpoint */ saveJeaContext(nodeName, endpoint) { this.authorizationManager.saveJeaContext(nodeName, endpoint); } /** * Gets the JEA powershell endpoint, if it exists * @param nodeName The node name */ getJeaEndpoint(nodeName) { return this.authorizationManager.getJeaEndpoint(nodeName); } /** * Creates service node API for Gateway V2. * * @param serviceName the name of service. * @param apiName the name of api. * @param nodeName the name of node. * @param remained the remained URL after it including option parameters. * @returns URL string. */ getServiceUrl(serviceName, apiName, nodeName, remained) { // 1) if null or empty, it's empty. // 2) if start with "?", remains as is. // 3) if not started with "/", add "/". remained = remained ?? ''; if (remained.length > 0 && !remained.startsWith('/')) { if (!remained.startsWith('?')) { remained = `/${remained}`; } } // for example, "/api/services/WinREST/PowerShell/nodes/computer-abc/invoke" return `/Services/${serviceName}/${apiName}/nodes/${nodeName}${remained}`; } /** * Adds default parameters to a NodeRequest * * @param method the http method to use * @param relativeUrl the relative Url after "/api/" * @param body the body string JSON.stringfy'ed * @param request the node request object to extend. */ createNodeRequest(request, nodeName) { // if we did not specify no auth, and we are not using a custom token... request = MsftSme.deepAssign({}, request); if (!request.noAuth && !request.authToken) { // ...then add node specific authorization handlers request.retryHandlers = (request.retryHandlers || []).concat([{ canHandle: (code, error) => this.authorizationManager.canHandleAjaxFailure(code, error), handle: (code, originalRequest, error) => this.authorizationManager.handleAjaxFailure(code, originalRequest, error, nodeName) }]); } const oldBeforeCall = request.beforeCall; // Add before call handler to wait for any pending node authorization request.beforeCall = pendingRequest => { let observable = null; if (!request.authToken) { // if we dont have an authToken, then make sure we are not waiting on one. observable = this.authorizationManager.authAwaiter .pipe(map(() => this.authorizationManager.addAuthorizationRequestHeader(pendingRequest, nodeName))); } else { observable = of(this.authorizationManager.addAuthorizationRequestHeader(pendingRequest, nodeName, request.authToken)); } if (oldBeforeCall) { return oldBeforeCall(request).pipe(mergeMap(() => observable)); } return observable; }; request.headers = request.headers || {}; if (request.logAudit === true || request.logAudit === false) { request.headers[headerConstants.LOG_AUDIT] = request.logAudit ? 'true' : 'false'; } if (request.logTelemetry === true || request.logTelemetry === false) { request.headers[headerConstants.LOG_TELEMETRY] = request.logTelemetry ? 'true' : 'false'; } const endpoint = this.authorizationManager.getJeaEndpoint(nodeName); if (request.powerShellEndpoint) { // Override JEA fallback if endpoint is explicitly set for debugging purposes request.headers[headerConstants.POWERSHELL_ENDPOINT] = request.powerShellEndpoint; } else if (endpoint) { request.headers[headerConstants.POWERSHELL_ENDPOINT] = endpoint; } if (request.authenticationMechanism === 'Credssp') { request.headers[headerConstants.AUTHENTICATION_MECHANISM] = request.authenticationMechanism; } return request; } /** * Get node name and node url. * @param nodeOrService The node name or service request object. * @param remained The remained url. * @returns node name and node url. */ getNodeUrl(nodeOrService, remained) { if (typeof nodeOrService === 'string') { const nodeName = nodeOrService; return { nodeName, relativeUrl: this.getNodeMappedUrl(nodeName, remained) }; } const service = nodeOrService; return { nodeName: service.nodeName, relativeUrl: this.getServiceUrl(service.serviceName, service.controllerName, service.nodeName, remained) }; } /** * Creates a Node url * * @param nodeName the name of the node to make a call against * @param relativeUrl the relative Url after "/nodes/<nodeName>/" */ getNodeMappedUrl(nodeName, relativeUrl) { if (EnvironmentModule.isGatewayV200) { const translation = GatewayUrlTranslator.translate(relativeUrl); if (translation) { return `${translation.startUrl}/nodes/${nodeName}/${translation.newUrl}`; } SmeWebTelemetry.traceAction(null, { content: { message: 'Could not get translation for URL: {0}'.format(relativeUrl), action: 'TranslateUrlToGateWayV2' } }, { type: 'error' }); throw new Error(MsftSme.getStrings().MsftSmeShell.Core.TranslateGatewayUrls.Url.Not.expected.ErrorMessage .format(relativeUrl)); } // create node url from current url if (!relativeUrl.startsWith('/')) { relativeUrl = `/${relativeUrl}`; } relativeUrl = Net.updateApiVersion20190201(relativeUrl); return `/nodes/${nodeName}${relativeUrl}`; } } //# sourceMappingURL=node-connection.js.map