PUT in BotService was replaced by GET - the bot was unusable.

This commit is contained in:
Rodrigo Rodriguez (pragmatismo.io) 2018-11-01 15:11:23 -03:00
parent fa8e310a2e
commit 4315449a91
4 changed files with 97 additions and 110 deletions

View file

@ -79,37 +79,6 @@ export class GBAdminService {
return Promise.resolve(obj.value); return Promise.resolve(obj.value);
} }
public static async acquireMsGraphTokenFromUsername(username, password) {
return new Promise<string>(async (resolve, reject) => {
let resource = "https://graph.microsoft.com";
let authenticatorAuthorityHostUrl = "https://login.microsoftonline.com";
let authenticatorTenant = "pragmatismo.onmicrosoft.com";
let authenticatorClientId = "0ffice19-91d5-41ea-98a4-ceea1655cc0b";
let authorizationUrl = UrlJoin(
authenticatorAuthorityHostUrl,
authenticatorTenant,
"/oauth2/authorize"
);
var authenticationContext = new AuthenticationContext(authorizationUrl);
authenticationContext.acquireTokenWithUsernamePassword(
resource,
username,
password,
authenticatorClientId,
async (err, res) => {
if (err) {
reject(err);
} else {
let token = res as TokenResponse;
resolve(token.accessToken);
}
}
);
});
}
public async acquireElevatedToken(instanceId): Promise<string> { public async acquireElevatedToken(instanceId): Promise<string> {
return new Promise<string>(async (resolve, reject) => { return new Promise<string>(async (resolve, reject) => {
let instance = await this.core.loadInstanceById(instanceId); let instance = await this.core.loadInstanceById(instanceId);
@ -195,7 +164,22 @@ export class GBAdminService {
maximumLength: 14 maximumLength: 14
}; };
let password = passwordGenerator.generatePassword(options); let password = passwordGenerator.generatePassword(options);
password = password.replace(/[=:;\?]/g, ""); password = password.replace(/@[=:;\?]/g, "#");
return password; return password;
} }
public static getRndReadableIdentifier() {
const passwordGenerator = new PasswordGenerator();
const options = {
upperCaseAlpha: false,
lowerCaseAlpha: true,
number: false,
specialCharacter: false,
minimumLength: 12,
maximumLength: 14
};
let name = passwordGenerator.generatePassword(options);
return name;
}
} }

View file

@ -81,8 +81,10 @@ export class AzureDeployerService extends GBService {
let culture = "en-us"; let culture = "en-us";
// Tries do get information from .env file otherwise asks in command-line. // Tries do get information from .env file otherwise asks in command-line.
let instance: IGBInstance = {}; let instance: IGBInstance = {};
instance = await this.ensureConfiguration(instance); instance = await this.ensureConfiguration(instance);
instance.marketplacePassword = GBAdminService.getRndPassword();
let spinner = new Spinner("%s"); let spinner = new Spinner("%s");
spinner.start(); spinner.start();
@ -91,12 +93,19 @@ export class AzureDeployerService extends GBService {
let keys: any; let keys: any;
let name = instance.botId; let name = instance.botId;
instance.marketplacePassword = GBAdminService.getRndPassword();
await this.internalDeployApp(name, instance.marketplacePassword)
logger.info(`Deploying Deploy Group (It may take a few minutes)...`); logger.info(`Deploying Deploy Group (It may take a few minutes)...`);
await this.createDeployGroup(name, instance.cloudLocation); await this.createDeployGroup(name, instance.cloudLocation);
instance = await this.deployBootBot(
instance,
name,
`${proxyAddress}/api/messages/${name}`,
instance.nlpAppId,
instance.nlpKey,
instance.cloudSubscriptionId
);
logger.info(`Deploying Bot Server...`); logger.info(`Deploying Bot Server...`);
let serverFarm = await this.createHostingPlan( let serverFarm = await this.createHostingPlan(
name, name,
@ -110,10 +119,9 @@ export class AzureDeployerService extends GBService {
instance.cloudLocation instance.cloudLocation
); );
let administratorLogin = `sa${GBAdminService.getRndPassword()}`;
let administratorPassword = GBAdminService.getRndPassword();
logger.info(`Deploying Bot Storage...`); logger.info(`Deploying Bot Storage...`);
let administratorLogin = `sa${GBAdminService.getRndReadableIdentifier()}`;
let administratorPassword = GBAdminService.getRndPassword();
let storageServer = `${name}-storage-server`; let storageServer = `${name}-storage-server`;
let storageName = `${name}-storage`; let storageName = `${name}-storage`;
await this.createStorageServer( await this.createStorageServer(
@ -124,7 +132,6 @@ export class AzureDeployerService extends GBService {
storageServer, storageServer,
instance.cloudLocation instance.cloudLocation
); );
await this.createStorage( await this.createStorage(
name, name,
storageServer, storageServer,
@ -195,7 +202,7 @@ export class AzureDeployerService extends GBService {
culture, culture,
instance.nlpAuthoringKey instance.nlpAuthoringKey
); );
let appId = GBAdminService.generateUuid();
instance.nlpEndpoint = nlp.endpoint; instance.nlpEndpoint = nlp.endpoint;
instance.nlpKey = keys.key1; instance.nlpKey = keys.key1;
instance.nlpAppId = nlpAppId; instance.nlpAppId = nlpAppId;
@ -205,10 +212,9 @@ export class AzureDeployerService extends GBService {
instance, instance,
name, name,
`${proxyAddress}/api/messages/${name}`, `${proxyAddress}/api/messages/${name}`,
null, instance.nlpAppId,
null, instance.nlpKey,
instance.cloudSubscriptionId, instance.cloudSubscriptionId
appId
); );
spinner.stop(); spinner.stop();
@ -371,9 +377,34 @@ export class AzureDeployerService extends GBService {
endpoint, endpoint,
nlpAppId, nlpAppId,
nlpKey, nlpKey,
subscriptionId, subscriptionId
appId
) { ) {
let appId = GBConfigService.get("MSAPP_ID");
let appPassword = GBConfigService.get("MSAPP_PASSWORD");
if (!appId || !appPassword) {
process.stdout.write(
"Sorry, this part cannot be automated yet due to Microsoft schedule, please go to https://apps.dev.microsoft.com/portal/register-app to generate manually an App ID and App Secret.\n"
);
}
let retriveAppId = () => {
if (!appId) {
process.stdout.write("Generated Application Id (MSAPP_ID):");
appId = scanf("%s").replace(/(\n|\r)+$/, "");
}
};
let retriveAppPassword = () => {
if (!appPassword) {
process.stdout.write("Generated Password (MSAPP_PASSWORD):");
appPassword = scanf("%s").replace(/(\n|\r)+$/, "");
}
};
retriveAppId();
retriveAppPassword();
await this.internalDeployBot( await this.internalDeployBot(
instance, instance,
this.accessToken, this.accessToken,
@ -385,10 +416,12 @@ export class AzureDeployerService extends GBService {
"global", "global",
nlpAppId, nlpAppId,
nlpKey, nlpKey,
subscriptionId, appId,
appId appPassword,
subscriptionId
); );
instance.marketplaceId = appId; instance.marketplaceId = appId;
instance.marketplacePassword = appPassword;
instance.botId = botId; instance.botId = botId;
return instance; return instance;
@ -424,46 +457,12 @@ export class AzureDeployerService extends GBService {
req.headers = {}; req.headers = {};
req.headers["Content-Type"] = "application/json; charset=utf-8"; req.headers["Content-Type"] = "application/json; charset=utf-8";
req.headers["accept-language"] = "*"; req.headers["accept-language"] = "*";
req.headers["x-ms-client-request-id"] = GBAdminService.generateUuid();
req.headers["Authorization"] = "Bearer " + accessToken; req.headers["Authorization"] = "Bearer " + accessToken;
let httpClient = new ServiceClient(); let httpClient = new ServiceClient();
let res = await httpClient.sendRequest(req); let res = await httpClient.sendRequest(req);
// TODO: Check res for error.
} }
private async internalDeployApp(name, pass) {
let username = GBConfigService.get("CLOUD_USERNAME");
let password = GBConfigService.get("CLOUD_PASSWORD");
let accessToken = await GBAdminService.acquireMsGraphTokenFromUsername(username, password);
let graphUrl = "https://graph.microsoft.com";
let expiresOn = new Date().toISOString();
let parameters = {
displayName: name,
passwordCredentials: [
{
secretText: pass,
endDateTime: expiresOn
}
]
};
let req = new WebResource();
req.method = "POST";
req.url = `${graphUrl}/beta/applications`;
req.headers = {};
req.headers["Content-Type"] = "application/json; charset=utf-8";
req.headers["accept-language"] = "*";
req.headers["x-ms-client-request-id"] = GBAdminService.generateUuid();
req.headers["Authorization"] = "Bearer " + accessToken;
req.body = parameters;
let httpClient = new ServiceClient();
return await httpClient.sendRequest(req);
}
/** /**
* @see https://github.com/Azure/azure-rest-api-specs/blob/master/specification/botservice/resource-manager/Microsoft.BotService/preview/2017-12-01/botservice.json * @see https://github.com/Azure/azure-rest-api-specs/blob/master/specification/botservice/resource-manager/Microsoft.BotService/preview/2017-12-01/botservice.json
*/ */
@ -478,14 +477,16 @@ export class AzureDeployerService extends GBService {
location, location,
nlpAppId, nlpAppId,
nlpKey, nlpKey,
subscriptionId, appId,
appId appPassword,
subscriptionId
) { ) {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
let baseUrl = `https://management.azure.com/`; let baseUrl = `https://management.azure.com/`;
await this.registerProviders(subscriptionId, baseUrl, accessToken); await this.registerProviders(subscriptionId, baseUrl, accessToken);
let appPassword = GBAdminService.getRndPassword(); instance.marketplaceId = appId;
instance.marketplacePassword = appPassword;
let parameters = { let parameters = {
location: location, location: location,
@ -499,12 +500,12 @@ export class AzureDeployerService extends GBService {
displayName: name, displayName: name,
endpoint: endpoint, endpoint: endpoint,
iconUrl: iconUrl, iconUrl: iconUrl,
luisAppIds: [nlpAppId], //luisAppIds: [nlpAppId],
luisKey: nlpKey, //luisKey: nlpKey,
msaAppId: appId, msaAppId: appId,
msaAppPassword: appPassword, msaAppPassword: appPassword,
enabledChannels: ["webchat", "skype", "facebook"], //enabledChannels: ["webchat"], // , "skype", "facebook"],
configuredChannels: ["webchat", "skype", "facebook"] configuredChannels: ["webchat"] // , "skype", "facebook"]
} }
}; };
@ -524,7 +525,9 @@ export class AzureDeployerService extends GBService {
reject(res.bodyAsText); reject(res.bodyAsText);
return; return;
} }
logger.info(`Bot creation request done waiting for key generation...`); logger.info(`Bot creation request done waiting for key generation...`);
resolve(instance);
setTimeout(async () => { setTimeout(async () => {
try { try {
@ -535,18 +538,13 @@ export class AzureDeployerService extends GBService {
req = this.createRequestObject( req = this.createRequestObject(
url, url,
accessToken, accessToken,
"PUT", "GET",
JSON.stringify(parameters) JSON.stringify(parameters)
); );
let resChannel = await httpClient.sendRequest(req); let resChannel = await httpClient.sendRequest(req);
console.log(resChannel.bodyAsText);
let key = (resChannel.bodyAsJson as any).properties.properties let key = (resChannel.bodyAsJson as any).properties.properties
.sites[0].key; .sites[0].key;
instance.marketplacePassword = appPassword;
instance.webchatKey = key; instance.webchatKey = key;
resolve(instance); resolve(instance);
} catch (error) { } catch (error) {
reject(error); reject(error);
@ -561,7 +559,10 @@ export class AzureDeployerService extends GBService {
let password = GBConfigService.get("CLOUD_PASSWORD"); let password = GBConfigService.get("CLOUD_PASSWORD");
let subscriptionId = GBConfigService.get("CLOUD_SUBSCRIPTIONID"); let subscriptionId = GBConfigService.get("CLOUD_SUBSCRIPTIONID");
let accessToken = await GBAdminService.getADALTokenFromUsername(username, password); let accessToken = await GBAdminService.getADALTokenFromUsername(
username,
password
);
let httpClient = new ServiceClient(); let httpClient = new ServiceClient();
let parameters = { let parameters = {

View file

@ -1,8 +1,8 @@
/*****************************************************************************\ /*****************************************************************************\
| ( )_ _ | | ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ | | _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ _ _ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ | | ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/ \ /`\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) | | | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| |*| |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' | | | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | | | | | ( )_) | |
| (_) \___/' | | (_) \___/' |
@ -300,20 +300,22 @@ export class GBCoreService implements IGBCoreService {
public async writeEnv(instance: IGBInstance) { public async writeEnv(instance: IGBInstance) {
let env = let env =
`ADMIN_PASS=${instance.adminPass}\n` +
`ADDITIONAL_DEPLOY_PATH=\n` + `ADDITIONAL_DEPLOY_PATH=\n` +
`ADMIN_PASS=${instance.adminPass}\n` +
`CLOUD_SUBSCRIPTIONID=${instance.cloudSubscriptionId}\n` +
`CLOUD_LOCATION=${instance.cloudLocation}\n` +
`CLOUD_GROUP=${instance.botId}\n` +
`CLOUD_USERNAME=${instance.cloudUsername}\n` +
`CLOUD_PASSWORD=${instance.cloudPassword}\n` +
`MSAPP_ID=${instance.marketplaceId}\n`+
`MSAPP_PASSWORD=${instance.marketplacePassword}\n`+
`NLP_AUTHORING_KEY=${instance.nlpAuthoringKey}\n`+
`STORAGE_DIALECT=${instance.storageDialect}\n` + `STORAGE_DIALECT=${instance.storageDialect}\n` +
`STORAGE_SERVER=${instance.storageServer}.database.windows.net\n` + `STORAGE_SERVER=${instance.storageServer}.database.windows.net\n` +
`STORAGE_NAME=${instance.storageName}\n` + `STORAGE_NAME=${instance.storageName}\n` +
`STORAGE_USERNAME=${instance.storageUsername}\n` + `STORAGE_USERNAME=${instance.storageUsername}\n` +
`STORAGE_PASSWORD=${instance.storagePassword}\n` + `STORAGE_PASSWORD=${instance.storagePassword}\n` +
`STORAGE_SYNC=true\n` + `STORAGE_SYNC=true\n`;
`CLOUD_USERNAME=${instance.cloudUsername}\n` +
`CLOUD_PASSWORD=${instance.cloudPassword}\n` +
`CLOUD_SUBSCRIPTIONID=${instance.cloudSubscriptionId}\n` +
`CLOUD_LOCATION=${instance.cloudLocation}\n` +
`CLOUD_GROUP=${instance.botId}\n` +
`NLP_AUTHORING_KEY=${instance.nlpAuthoringKey}`;
fs.writeFileSync(".env", env); fs.writeFileSync(".env", env);
} }

View file

@ -108,7 +108,7 @@ export class GBServer {
bootInstance = await azureDeployer.deployFarm(proxyAddress); bootInstance = await azureDeployer.deployFarm(proxyAddress);
} catch (error) { } catch (error) {
logger.warn( logger.warn(
"Error while deploying to the cloud, please, cleanup any objects created before running again." "In case of error, please cleanup any infrastructure (cloud or on-premises) objects created before running again."
); );
throw error; throw error;
} }
@ -205,7 +205,7 @@ export class GBServer {
// Load all instances from .gbot found on deploy package directory. // Load all instances from .gbot found on deploy package directory.
if (!instances) { if (!instances) {
let saveInstance = new GuaribasInstance(bootInstance); let saveInstance = new GuaribasInstance(bootInstance);
saveInstance.save(); await saveInstance.save();
instances = await core.loadInstances(); instances = await core.loadInstances();
} }