Skip to content
This repository was archived by the owner on Nov 15, 2024. It is now read-only.

Commit c03eaa3

Browse files
committed
Updated mst bot documentation and app package management tools
1 parent ee914e0 commit c03eaa3

19 files changed

+212
-373
lines changed

api_server/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ api-server-*.info
99
sandbox/docker/extras/
1010
sandbox/docker/Dockerfile
1111
sandbox/docker/runtime.env
12+
etc/msteamsbot/dist/
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#!/usr/bin/env python3
2+
3+
# desc# create the app packages for integrating codestream to msteams
4+
5+
import os
6+
import sys
7+
import argparse
8+
import shutil
9+
import glob
10+
import re
11+
import json
12+
13+
sys.path.append(os.environ['DT_TOP'] + "/lib")
14+
import sysUtils as su
15+
import awsCS
16+
17+
18+
# create the app package (zip file) for the specified env & botId
19+
# and optionally distribute it
20+
def makeAppPackage(globalData, env, botId, manifestTemplate):
21+
outDir = f"{globalData['distRoot']}/{env}"
22+
if not os.path.exists(outDir):
23+
os.mkdir(outDir)
24+
# create the manifest
25+
manifest = su.expandTemplate(manifestTemplate, {'env': env, 'botId': botId})
26+
manifestData = json.loads(manifest)
27+
outFile = open(f"{outDir}/manifest.json", "w")
28+
outFile.write(manifest)
29+
outFile.close()
30+
# copy additional resource files
31+
for f in ['color.png', 'outline.png']:
32+
shutil.copyfile(f"{globalData['templateDir']}/{f}", f"{outDir}/{f}")
33+
# create the zip file named based on env and version
34+
envString = "" if env == "prod" else f"-{env}"
35+
zipName = f"codestream-msteamsbot{envString}-{manifestData['version']}.zip"
36+
su.shellExecNoBuffer(f"zip -q ../{zipName} *", workingDir=outDir, abortOnFail=True, printCmd=True)
37+
# distribute the zip file via S3
38+
if globalData['args'].distribute:
39+
cmd = f"aws s3 cp {globalData['distRoot']}/{zipName} {globalData['distributionKeyPrefix']}/{zipName} --sse"
40+
su.shellExecNoBuffer(cmd, abortOnFail=True, printCmd=True)
41+
42+
43+
# create the package contents from a key management database config file
44+
def makeAppPackageFromEnvFile(globalData, manifestTemplate, envFile):
45+
rc = 0
46+
match = re.search(r'.*\/teams-(.+).cfg$', envFile)
47+
if match:
48+
env = "pd" if match.group(1) == "dev" else match.group(1)
49+
envData = su.readKeyValueFile(envFile)
50+
# su.dumpDict(envData)
51+
if 'botAppId' in envData:
52+
makeAppPackage(globalData, env, envData['botAppId'], manifestTemplate)
53+
else:
54+
print(f"botAppId not defined for {env} environment")
55+
else:
56+
su.printErr(f"could not determine env from {envFile}")
57+
rc = 1
58+
return rc
59+
60+
61+
globalData = {
62+
'distributionKeyPrefix': f"{awsCS.awsCS().getCloudFrontProperty('assets', 's3BucketPrefix')}/mstbot",
63+
'botDir': f"{os.environ['CS_API_TOP']}/etc/msteamsbot",
64+
'templateDir': f"{os.environ['CS_API_TOP']}/etc/msteamsbot/template",
65+
'distRoot': f"{os.environ['CS_API_TOP']}/etc/msteamsbot/dist",
66+
}
67+
68+
parser = argparse.ArgumentParser(description="msteams bot app package creator")
69+
parser.add_argument('--debug', action='store_true', default=False, help='show debugging output')
70+
parser.add_argument('--verbose', action='store_true', default=False, help='show verbose output')
71+
parser.add_argument('-e', '--env', type=str, help="environment")
72+
parser.add_argument('-b', '--botId', type=str, help="bot registration app ID")
73+
parser.add_argument('--use-keydb', action='store_true', default=False, help="get app IDs from key management DB")
74+
parser.add_argument('--distribute', action='store_true', default=False, help="copy zips to S3 using the AWS CLI")
75+
args = parser.parse_args()
76+
77+
ec = 0
78+
globalData['args'] = args
79+
if args.debug:
80+
su.dumpDict(globalData, None, "globalData:")
81+
manifestTemplate = su.readFileIgnoreComments(f"{globalData['templateDir']}/manifest.json")
82+
83+
if not os.path.exists(globalData['distRoot']):
84+
print(f"creating {globalData['distRoot']}")
85+
os.mkdir(globalData['distRoot'])
86+
87+
if args.env and args.botId:
88+
makeAppPackage(globalData, args.env, args.botId, manifestTemplate)
89+
elif args.use_keydb:
90+
if not os.environ['KM_PKI']:
91+
su.printErr("where is the key management database (KM_PKI is not defined)?")
92+
exit(1)
93+
# read environments & botIds from the secrets database
94+
for envFile in glob.glob(f"{os.environ['KM_PKI']}/secrets/microsoft/teams-*.cfg"):
95+
ec += makeAppPackageFromEnvFile(globalData, manifestTemplate, envFile)
96+
else:
97+
parser.print_help()
98+
exit(1)
99+
exit(ec)

api_server/bin/cs_msteams_bot_manifest_creator.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env node
22

3+
34
// utility script to create a manifest file for an MS Teams bot
45

56
/* eslint no-console: 0 */
@@ -31,7 +32,11 @@ if (!Commander.botId && !Commander.env) {
3132
text = text.replace(/{{env}}/g, `-${Commander.env}`);
3233
}
3334
let json = JSON.parse(text);
34-
fs.writeFileSync(`${process.env.CS_API_TOP}/etc/msteamsbot/${Commander.env}/manifest.json`, JSON.stringify(json, null, 4));
35+
let outputDir = `${process.env.CS_API_TOP}/etc/msteamsbot/dist`;
36+
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir);
37+
outputDir += '/' + Commander.env;
38+
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir);
39+
fs.writeFileSync(`${outputDir}/manifest.json`, JSON.stringify(json, null, 4));
3540
process.exit();
3641
}
3742
catch (error) {

api_server/etc/msteamsbot/README.md

Lines changed: 105 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,123 @@
11
# MS Teams app / bot
2-
The following describes how to setup an MS Teams bot/app along with
3-
the logic surrounding it in the api_server. Unlike most 3rd party api flows, with this integration, we are not getting an accessToken and querying a 3rd party api, but rather, we are gathering information from MS Teams teams, storing that in mongo, then querying it from the lsp agent.
4-
5-
## App/Bot Registration
6-
7-
There is a 2-step process for creating bots in the Microsoft world:
8-
9-
1 - first, create the bot here https://dev.botframework.com/bots
10-
- To create a new bot: https://dev.botframework.com/bots/new
11-
12-
2 - Then create an 'app' for it in Azure
13-
- Go to https://portal.azure.com
14-
- Go to `App registrations`
15-
- (or just go here, which might not work: https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps)
16-
17-
We have a few bots/apps that have been created in the botframework site, they are:
18-
19-
#### CodeStream (prod)
20-
7cf49ab7-8b65-4407-b494-f02b525eef2b
21-
22-
#### CodeStream-QA
23-
a0b30480-2944-46a6-97ca-192a655cdb62
2+
The following describes how to setup an MS Teams bot/app along with the logic
3+
surrounding it in the api_server. Unlike most 3rd party api flows, with this
4+
integration, we are not getting an accessToken and querying a 3rd party api, but
5+
rather, we are gathering information from MS Teams teams, storing that in mongo,
6+
then querying it from the lsp agent.
7+
8+
9+
## Create the bot channel registration resource in Azure
10+
11+
To link MS Teams to the CodeStream bots (our API services which run in our AWS
12+
account) you must create _Bot Channels Registration_ resources (one per
13+
environment) in the Azure Portal.
14+
15+
1. Login to the [Azure Portal](https://portal.azure.com)
16+
1. Hamburger Menu (upper left) > '+ Create a resource'
17+
1. Search for the **bot channels registration** resource and create one.
18+
<image src="screens/01-find-bot-service.png" width="400">
19+
<br>
20+
<image src="screens/02-create-bot-channel-reg.png" width="400">
21+
1. Submit the **bot channels registration** form and wait for the resource to
22+
become available.
23+
<image src="screens/03-bot-channel-reg-form.png" width="400">
24+
<br>
25+
1. **Bot handles** are globally unique. Our standard is `codestreambot-<env>`
26+
1. An Azure Subscription - use `R&D`
27+
1. A Resource Group - create a dedicated one or use `codestream-core`
28+
1. Location - use `East US`
29+
1. Pricing Tier - Use `S1`
30+
1. Messaging Endpoint - For developer local environments, use
31+
`https://csaction.codestream.us/no-auth/provider-action/msteams/<your-host>/development`
32+
which will forward to port 12079 on `<your-host>`. For other
33+
environments have operations edit and deploy
34+
**ops_tools/etc/nginx/proxy/codestream-csaction.conf.template**
35+
accordingly.
36+
1. Turn **Application Insights** off
37+
1. Submit the form - **Create** button on the bottom - to submit the
38+
request to Azure. You'll be notified via the Azure Portal dashboard when
39+
your resource is ready (2-5 minutes).
40+
1. Hamburger Menu > Azure Active Directory > App Registrations > _select your app_
41+
1. Select _Certificates & Secrets_ under the _Manage_ section and create a new
42+
client secret. <image src="screens/04-generate-new-client-secret.png"
43+
width="400"><br>_**Make sure you save the secret and add it to your API
44+
server's configuration file.**_
45+
1. Delete the secret that was automtically created with the resource. Since you
46+
don't know its value, it is of no use.
47+
1. Finally, in the branding section, you can add an icon, links, etc...
48+
<image src="screens/05-complete-branding-data.png" width="400"><br>
49+
50+
51+
## Creating the MS Teams App Packages
52+
53+
MST App Packages are zip files containing a manifest and some icons. App
54+
packages are then loaded into your MS Teams account in order to connect it to
55+
your CodeStream bot apps (backend api server).
56+
57+
The App packages can be distributed to _side load_ them into MS Teams. The
58+
production app package is submitted to the Microsoft AppSource (formerly MST App
59+
Marketplace) for review and approval.
60+
61+
To create app packages you'll need the environment you're creating a package for
62+
as well as the _Application (client) ID_ associated with the bot channels
63+
resource you just created. You can see it on the **Overview** blade of your App
64+
registration.
65+
66+
### Environments & App IDs (aka botIds)
67+
68+
For operations-managed environments (prod, qa, pd, ...) the Application IDs are
69+
read from the Secrets database. Personal and other Application IDs can be saved
70+
here.
71+
72+
| Env | Application (client) ID - aka botId |
73+
| --- | --- |
74+
| prod | 7cf49ab7-8b65-4407-b494-f02b525eef2b (source of truth is the secrets database) |
75+
| pd | 1a08df08-b652-464a-bac3-bfa386dcfa6d (source of truth is the secrets database) |
76+
| qa | a0b30480-2944-46a6-97ca-192a655cdb62 (source of truth is the secrets database) |
77+
| brian | 7bce9cff-9fd1-4e05-b7b5-5638ec468880 |
78+
79+
### Package Creation Commands
80+
To create an App Package using dev_tools:
81+
```
82+
$ cs_api-msteams_bot_app_pkg_creator -e <env> -b <bot-application-id>
83+
```
84+
Create a manifest file only (does not require dev_tools):
85+
```
86+
$ cd $CS_API_TOP
87+
$ node bin/cs_msteams_bot_manifest_creator.js -e <env> -b <bot-application-id>
88+
```
89+
Create App Packages for all managed environments and optionally distribute them
90+
to our CDN (you must have access to the secrets database and S3 asset
91+
distribution tree).
92+
```
93+
$ cs_api-msteams_bot_app_pkg_creator --use-keydb [--distribute]
94+
```
95+
Once distributed, you can fetch the packages (except production) with:
96+
`https://assets.codestream.com/mstbot/codestream-msteamsbot-<env>-<version>.zip`
2497

25-
#### CodeStream-PD
26-
1a08df08-b652-464a-bac3-bfa386dcfa6d
98+
For production, use:
99+
`https://assets.codestream.com/mstbot/codestream-msteamsbot-<version>.zip`
27100

28-
#### CodeStream-Brian
29-
7bce9cff-9fd1-4e05-b7b5-5638ec468880
30101

31-
Note: these GUIDs are created via Azure (step 2 above)
102+
### Additional Publishing Documentation
103+
https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/appsource/publish
32104

33-
MS Teams apps are essentially just a manifest.json file that dictates its various configuration settings and features. Bots are
34-
optional and are part of the app's manifest. You will need to set a username/password (via azure) for these bots, the api_server will require them.
105+
https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/appsource/prepare/overview
35106

36107

37108
## Developing
38-
Use the App Studio app from within the Teams app to test your app's manifest, as well as serve as a UI for editing it. From here, you can attach the bot, as well as install it locally for testing
39109

40-
https://aka.ms/InstallTeamsAppStudio
110+
Use the App Studio app from within the Teams app to test your app's manifest, as
111+
well as serve as a UI for editing it. From here, you can attach the bot, as well
112+
as install it locally for testing
41113

114+
https://aka.ms/InstallTeamsAppStudio
42115

43-
## Manifest
44-
45-
run the following commands to generate the env=specific manifest file(s)
46-
```
47-
node bin/cs_msteams_bot_manifest_creator.js -b 7bce9cff-9fd1-4e05-b7b5-5638ec468880 -e brian
48-
49-
node bin/cs_msteams_bot_manifest_creator.js -b 1a08df08-b652-464a-bac3-bfa386dcfa6d -e pd
50-
51-
node bin/cs_msteams_bot_manifest_creator.js -b a0b30480-2944-46a6-97ca-192a655cdb62 -e qa
52-
53-
node bin/cs_msteams_bot_manifest_creator.js -b 7cf49ab7-8b65-4407-b494-f02b525eef2b -e prod
54-
```
55-
56-
## Publishing
57-
58-
Zip the inner contents of the environment you're targetting (should be 3 files: 1 manifest, 2 images)
59-
60-
https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/appsource/publish
61-
62-
https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/appsource/prepare/overview
63-
64-
## Dev logic
116+
### Dev logic
65117

66118
the `hasSharing` flag is enabled for `modules/msteams_auth/msteams_auth.js`. While MS Teams does not follow the same flow
67119
as Slack, it does share a lot of the glue that makes it work -- as it follows the notion of it being a `provider`. As user triggers this flow in the IDE by attempting to add an `MS Teams Organization` from the codemark sharing dropdown.
68120

69-
### Installation
70-
One of the users in the MS Teams organization will have to install the CodeStream for MS Teams app. At this point, it will be available for the entire team, though one of the users (that is also a CodeStream user) will have to link their MS Teams organization (known as a tenant) to a CodeStream user/team.
71-
72121
### SignIn
73122
A user gets associated with CodeStream by signing into CodeStream via the web by issuing the `signin` command from the personal CodeStream bot chat. This eventually creates a `signinToken` which is tied to the CS `userId`, CS `teamId` and the MS Teams `tenantId`. If a user is on > 1 team, they will be prompted with a team selector.
74123

-7.1 KB
Binary file not shown.

0 commit comments

Comments
 (0)