{"id":51264504,"url":"https://github.com/jsabo/teleport-msteams-plugin","last_synced_at":"2026-06-29T14:32:27.076Z","repository":{"id":362599051,"uuid":"1259453623","full_name":"jsabo/teleport-msteams-plugin","owner":"jsabo","description":"Setup guide and local testing environment for the Teleport MS Teams access request plugin","archived":false,"fork":false,"pushed_at":"2026-06-05T03:12:36.000Z","size":56,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-05T04:08:56.671Z","etag":null,"topics":["access-requests","docker-compose","microsoft-teams","msteams","tbot","teleport"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jsabo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-04T14:21:51.000Z","updated_at":"2026-06-05T03:12:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jsabo/teleport-msteams-plugin","commit_stats":null,"previous_names":["jsabo/teleport-msteams-plugin"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/jsabo/teleport-msteams-plugin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsabo%2Fteleport-msteams-plugin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsabo%2Fteleport-msteams-plugin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsabo%2Fteleport-msteams-plugin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsabo%2Fteleport-msteams-plugin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jsabo","download_url":"https://codeload.github.com/jsabo/teleport-msteams-plugin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jsabo%2Fteleport-msteams-plugin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34931587,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-29T02:00:05.398Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["access-requests","docker-compose","microsoft-teams","msteams","tbot","teleport"],"created_at":"2026-06-29T14:32:23.238Z","updated_at":"2026-06-29T14:32:27.062Z","avatar_url":"https://github.com/jsabo.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# teleport-msteams-plugin\n\nSetup guide for the [Teleport MS Teams access request plugin](https://goteleport.com/docs/identity-governance/access-requests/plugins/msteams/). Covers Azure Bot configuration, Cloud plugin enrollment, Teams app upload, and recipient routing via Access Monitoring Rules.\n\nThe Docker Compose setup at the bottom of this guide is a troubleshooting tool — use it if the Cloud plugin isn't delivering notifications and you need to isolate whether the issue is Azure permissions, the Teams app installation, or the plugin itself.\n\n---\n\n## Prerequisites\n\n- Teleport Cloud cluster\n- Azure subscription — someone with **Application Administrator** (or higher) to grant Graph API admin consent\n- Microsoft Teams — someone with **Teams Administrator** (or higher) to upload the custom app\n\n\u003e **Two admin domains are involved and are often owned by different people:**\n\u003e - Steps 1–4 (Azure Bot, API permissions, admin consent) require an **Azure AD admin**\n\u003e - Steps 5–6 (Teams app upload, add to channel) require a **Teams admin**\n\u003e\n\u003e Identify both people before starting.\n\n---\n\n## Azure setup (required once)\n\n### 1 — Create an Azure Bot\n\nGo to [Create an Azure Bot](https://portal.azure.com/#create/Microsoft.AzureBot) in the Azure Portal and fill in the **Basics** tab:\n\n- **Bot handle**: `teleport-msteams-plugin` (or any unique name)\n- **Subscription** and **Resource group**: use your existing subscription; create a new resource group named after the bot handle\n- **Data residency**: Global\n- **Pricing tier**: Standard\n- **Type of App**: Single Tenant\n- **Creation type**: Create new Microsoft App ID\n\nClick **Review + create**, then **Create**. Azure automatically creates an app registration alongside the bot — you do not need to create one separately.\n\n### 2 — Note your App ID and Tenant ID\n\nOnce deployed, open the bot resource → **Settings** → **Configuration**:\n\n- **Microsoft App ID** — this is your `\u003cAZURE_APP_ID\u003e`\n- **App Tenant ID** — this is your `\u003cAZURE_TENANT_ID\u003e`\n\nSave both values.\n\n### 3 — Create a client secret\n\nFrom the Configuration page, click **Manage Password** next to the Microsoft App ID. This opens the app registration's **Certificates \u0026 secrets** page.\n\nClick **+ New client secret**:\n- **Description**: `teleport-msteams-plugin`\n- **Expires**: 730 days (24 months)\n\nClick **Add**. Copy the **Value** column immediately — it is only shown once. Save it somewhere secure; you will need it when enrolling the plugin.\n\n### 4 — API permissions\n\nStill in the app registration (reached via **Manage Password**), click **API permissions** in the left sidebar under **Manage**.\n\nClick **+ Add a permission** → **Microsoft Graph** → **Application permissions**.\n\nUse the search box to find and add these four permissions one at a time, clicking **Add permissions** after each:\n\n| Permission | Purpose |\n|---|---|\n| `AppCatalog.Read.All` | Used to list Teams apps and check if the app is installed |\n| `User.Read.All` | Used to get notification recipients |\n| `TeamsAppInstallation.ReadWriteSelfForUser.All` | Used to initiate communication with a user that never interacted with the Teams app before |\n| `TeamsAppInstallation.ReadWriteSelfForTeam.All` | Used to discover if the app is installed in the team |\n\nOnce all four appear in the **Configured permissions** table, click **Grant admin consent for \\\u003ctenant\\\u003e**. This requires **Application Administrator**, **Cloud Application Administrator**, or **Global Admin**. All four should show a green **Granted for \\\u003ctenant\\\u003e** status.\n\n\u003e All four use the **Self** variant — the plugin can only manage its own app's installation, never any other app. This is the least-privilege set.\n\n---\n\n## Enable the Cloud-hosted plugin\n\n\u003e See the [official Teleport MS Teams plugin docs](https://goteleport.com/docs/identity-governance/access-requests/plugins/msteams/) for full reference.\n\n**Teleport Web UI → Integrations → Microsoft Teams → Enroll**\n\nEnter the values from the Azure setup:\n\n| Field | Value |\n|---|---|\n| App ID | `\u003cAZURE_APP_ID\u003e` |\n| Tenant ID | `\u003cAZURE_TENANT_ID\u003e` |\n| App secret | your client secret value |\n| TeamsApp ID | leave blank — Teleport generates one |\n| Default Recipient | a Teams channel URL (Teams → right-click channel → **Get link to channel**) |\n\nClick **Connect Microsoft Teams**. The plugin will show as **Failed** until the Teams app is uploaded in the next steps — that is expected.\n\n---\n\n## Upload the Teams app\n\n### 5 — Download and patch the app package\n\nAfter enrolling, go to **Integrations → Microsoft Teams → Options → Download app.zip**.\n\nTeleport generates an `app.zip` containing the Teams app manifest. The manifest only includes `\"scopes\": [\"team\"]` — without adding `\"personal\"`, DM delivery silently fails regardless of permissions. Patch it before uploading:\n\n```bash\nunzip -q ~/Downloads/app.zip -d ~/Downloads/app-unpacked\n```\n\nOpen `~/Downloads/app-unpacked/manifest.json` and make these changes:\n\n1. Find `\"scopes\": [\"team\"]` inside the `bots` array and change it to `\"scopes\": [\"team\", \"personal\"]`\n2. Bump the `\"version\"` field only if you are **re-uploading** an existing app — Teams Admin Center rejects uploads where the version hasn't changed. For a **first upload**, leave the version as-is.\n\nThen repack:\n\n```bash\ncd ~/Downloads/app-unpacked \u0026\u0026 zip -j ../app-patched.zip color.png manifest.json outline.png\necho \"Ready to upload: ~/Downloads/app-patched.zip\"\n```\n\n### 6 — Upload to Teams Admin Center and add to a channel\n\nThis step requires a **Teams Administrator** or **Global Admin**.\n\n1. [Teams Admin Center](https://admin.teams.microsoft.com) → Teams apps → Manage apps →\n   **Upload new app** → select `~/Downloads/app-patched.zip`\n2. The app appears as \"TeleBot\" in the org app catalog. If your org requires admin\n   approval for custom apps, approve it from the same page.\n3. In [Azure Portal](https://portal.azure.com), open the bot resource → **Settings** →\n   **Channels** → add **Microsoft Teams**. Accept the terms of service. This connects the\n   bot to the Teams Bot Framework so it can send cards. Once added, an **Open in Teams**\n   link appears next to the Microsoft Teams channel.\n4. Click **Open in Teams**. This opens TeleBot's app card directly in Teams. Click **Add**,\n   then select the General channel of your target team.\n\n\u003e **Do not search for \"TeleBot\" in the Teams app store** — the search returns public apps\n\u003e only and will not find your org app. Use the **Open in Teams** link from the Azure Portal.\n\nThis installs TeleBot in the team, which is required before the plugin can post to any\nstandard channel in that team. General is just the installation point — notifications go to\nwhichever channel URL is configured in your recipients. Repeat for each team you want to\nreceive channel notifications.\n\n\u003e **Note:** Private channels are not supported. TeleBot installed at the team level can only post to standard channels.\n\nOnce TeleBot is in the org catalog and installed in a team, the plugin status will update.\nThe health check runs once at startup — if the plugin shows **Failed** after completing\nthese steps, trigger a recheck:\n\n```bash\ntctl get plugins --format text   # check current status\ntctl edit plugin/msteams         # opens editor; save without changes to trigger restart\n```\n\nAfter saving, run `tctl get plugins --format text` again — status should show `RUNNING`.\n\n---\n\n### Routing with Access Monitoring Rules\n\nThe Cloud plugin routes all notifications to the Default Recipient unless an [Access Monitoring Rule](https://goteleport.com/docs/identity-governance/access-requests/plugins/msteams/) matches. Use AMRs for per-role routing to different channels or individual users via DM.\n\n```yaml\nkind: access_monitoring_rule\nversion: v1\nmetadata:\n  name: msteams-channel-example\nspec:\n  subjects: [access_request]\n  condition: 'access_request.spec.roles.contains(\"\u003cROLE_NAME\u003e\")'\n  notification:\n    name: msteams\n    recipients:\n      - \"\u003cTEAMS_CHANNEL_URL\u003e\"   # channel\n      - \"user@example.com\"      # user DM (primary mail only)\n```\n\n```bash\ntctl create -f access-monitoring-rule.yaml\n```\n\nAMR recipients override the Default Recipient when the condition matches. The `contains` predicate requires an exact role name match.\n\n\u003e DM recipients must match the primary `mail` field in Azure AD — not proxy addresses or `.onmicrosoft.com` aliases.\n\n---\n\n## Troubleshooting with Docker Compose\n\nIf the Cloud plugin isn't delivering notifications, use this setup to validate your Azure configuration end-to-end. It runs the plugin locally so you can see exactly what's happening.\nSee the [official docs](https://goteleport.com/docs/identity-governance/access-requests/plugins/msteams/) for the full plugin reference.\n\n### What you need\n\n```bash\n# Write your Azure app secret to a file (mounted into the plugin container)\necho -n '\u003cclient secret value\u003e' \u003e app-secret\n\n# Create the bot identity in Teleport\ntctl create -f rbac.yaml\n\n# Generate a single-use join token for tbot\ntctl bots instances add msteams-plugin --format=json | jq -r '.token_id' \u003e token\n```\n\n\u003e The token is single-use. Once tbot joins, it stores its identity in the `tbot-state`\n\u003e Docker volume and renews automatically. Generate a new token only after `docker compose down -v`.\n\n### Generate app.zip and plugin.toml\n\nThe `configure` command generates a self-contained `app.zip` and TOML config. Use it when you want to run the plugin locally without enrolling via the Teleport UI:\n\n```bash\nsource .env\ndocker run --rm \\\n  -v \"$(pwd):/workspace\" \\\n  public.ecr.aws/gravitational/teleport-plugin-msteams:${TELEPORT_VERSION} \\\n  configure /workspace/assets \\\n  --appID  \"\u003cAZURE_APP_ID\u003e\" \\\n  --tenantID \"\u003cAZURE_TENANT_ID\u003e\" \\\n  --appSecret \"\u003cclient secret value\u003e\"\n```\n\n\u003e If you need to re-run `configure`, remove the output directory first: `rm -rf assets`\n\nOn success:\n```\n[1] Created target directory: /workspace/assets\n[2] Created /workspace/assets/app.zip\n\nTeamsAppID: \u003cgenerated-uuid\u003e\n```\n\nPatch `assets/app.zip` the same way as the Cloud flow (add `\"personal\"` scope, bump version), then upload `assets/app-patched.zip` to Teams Admin Center.\n\nGenerate `plugin.toml` from the configure output:\n\n**macOS:**\n```bash\ncp assets/teleport-msteams.toml plugin.toml\nsed -i '' \\\n  -e 's|addr = \"localhost:3025\"|addr = \"\u003cTELEPORT_PROXY\u003e\"|' \\\n  -e 's|identity = \"identity\"|identity = \"/identity/identity\"|' \\\n  -e 's|# refresh_identity = true.*$|refresh_identity = true|' \\\n  -e 's|app_secret = \".*\"|app_secret = \"/etc/plugin/app-secret\"|' \\\n  plugin.toml\n```\n\n**Linux:**\n```bash\ncp assets/teleport-msteams.toml plugin.toml\nsed -i \\\n  -e 's|addr = \"localhost:3025\"|addr = \"\u003cTELEPORT_PROXY\u003e\"|' \\\n  -e 's|identity = \"identity\"|identity = \"/identity/identity\"|' \\\n  -e 's|# refresh_identity = true.*$|refresh_identity = true|' \\\n  -e 's|app_secret = \".*\"|app_secret = \"/etc/plugin/app-secret\"|' \\\n  plugin.toml\n```\n\n\u003e **Required:** Open `plugin.toml` and update `[role_to_recipients]` — replace `\"*\" = [\"foo@example.com\"]` with your Teams channel URL. The plugin will not deliver notifications without a valid recipient.\n\nAlso update `\u003cTELEPORT_PROXY\u003e` in `tbot.yaml` with your cluster address.\n\n### Files\n\n| File | Purpose |\n|---|---|\n| `docker-compose.yaml` | tbot + msteams plugin services |\n| `tbot.yaml` | tbot machine identity config |\n| `plugin.toml` | Plugin config — generated from configure output, gitignored |\n| `rbac.yaml` | Teleport bot definition |\n| `.env` | Image version (`TELEPORT_VERSION`) |\n| `token` | Join token — gitignored, single-use |\n| `app-secret` | Azure app client secret — gitignored |\n\n### Run\n\n```bash\ndocker compose up\n```\n\ntbot joins on first run and writes the identity to the shared `identity` volume. The msteams container restarts until the identity is available, then connects and logs \"Plugin is ready\".\n\n### Validate DM delivery\n\n```bash\nsource .env\ndocker run --rm \\\n  -v \"$(pwd)/plugin.toml:/etc/teleport-msteams.toml:ro\" \\\n  -v \"$(pwd)/app-secret:/etc/plugin/app-secret:ro\" \\\n  public.ecr.aws/gravitational/teleport-plugin-msteams:${TELEPORT_VERSION} \\\n  validate --config=/etc/teleport-msteams.toml user@example.com\n```\n\n\u003e If you see `Message sent, ID: ...` in the output, the DM was delivered successfully.\n\u003e The command may exit non-zero — check for that log line to confirm delivery.\n\n### Upgrading\n\n```bash\n# Update TELEPORT_VERSION in .env, then:\ndocker compose pull \u0026\u0026 docker compose up -d\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsabo%2Fteleport-msteams-plugin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjsabo%2Fteleport-msteams-plugin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjsabo%2Fteleport-msteams-plugin/lists"}