|
| 1 | +# Metered APIs guidance and random errors |
| 2 | + |
| 3 | +Using the Metered Microsoft Graph APIs plugin, customers can understand if they use metered APIs in Microsoft Graph and can test how their application will response to 402 Payment Required responses. |
| 4 | + |
| 5 | +Metered APIs allows you to get access to advanced capabilities in Microsoft Graph. They require an active Azure subscription with the calling application. Some of these metered APIs are protected and require additional validation beyond permissions and admin consent. The main goal of this guidance is to know that the APIs they are calling would require extra action when deployed in production and could incur a cost. |
| 6 | + |
| 7 | +## History |
| 8 | + |
| 9 | +| Version | Date | Comments | Author | |
| 10 | +| ------- | ---------- | ---------------------- | ---------------- | |
| 11 | +| 1.0 | 2023-03-20 | Initial specifications | @sebastienlevert | |
| 12 | + |
| 13 | +## Configuration |
| 14 | + |
| 15 | +N/A |
| 16 | + |
| 17 | +## Implementation |
| 18 | + |
| 19 | +> **Note** |
| 20 | +> This metered APIs plugin is only valid for Microsoft Graph requests. |
| 21 | +
|
| 22 | +### Guidance |
| 23 | + |
| 24 | +Metered APIs guidance will be implemented as a plugin, subscribed to one events: `BeforeRequest`. |
| 25 | + |
| 26 | +In the `BeforeRequest` event, the plugin will check if the request URL is part of the identified metered APIs. This list of APIs is documented in the official Microsoft Graph Docs [here](https://learn.microsoft.com/en-us/graph/metered-api-list?view=graph-rest-1.0). This list will likely grow but as a first step, we will be using a static configuration file to identify the endpoints to mark as metered. If the request is targeted at a metered API, we will emit a log message that will include text telling the developer the endpoint is metered and will include a link to the Metered APIs and services in Microsoft Graph documentation: `https://learn.microsoft.com/en-us/graph/metered-api-list`. |
| 27 | + |
| 28 | +#### Passthrough |
| 29 | + |
| 30 | +- The 'More info' is coming from the `billingInformation` property. |
| 31 | +- The 'Request access' is coming from the `registrationForm` property. |
| 32 | + |
| 33 | +```shell |
| 34 | +[ REQUEST ] GET https://graph.microsoft.com/v1.0/teams/*/channels/getAllMessages?model=A |
| 35 | +[ API ] ┌ Passed through |
| 36 | + └ GET https://graph.microsoft.com/v1.0/teams/*/channels/getAllMessages?model=A |
| 37 | +[ INFO ] ┌ This is a metered API. |
| 38 | + │ More info at https://learn.microsoft.com/en-us/graph/teams-licenses |
| 39 | + │ Request access at https://aka.ms/teamsgraph/requestaccess |
| 40 | + └ GET https://graph.microsoft.com/v1.0/teams/*/channels/getAllMessages?model=A |
| 41 | +``` |
| 42 | + |
| 43 | +#### Using the API without a payment model |
| 44 | + |
| 45 | +- The 'More info' is coming from the `billingInformation` property. |
| 46 | + |
| 47 | +```shell |
| 48 | +[ REQUEST ] GET hhttps://graph.microsoft.com/v1.0/teams/*/channels/getAllMessages |
| 49 | +[ API ] ┌ Passed through |
| 50 | + └ GET https://graph.microsoft.com/v1.0/teams/*/channels/getAllMessages |
| 51 | +[ WARNING ] ┌ You are using a metered API without a payment model parameter. You are currently in Evaluation Mode and the API will eventually stop returning data |
| 52 | + │ More info at https://learn.microsoft.com/en-us/graph/teams-licenses#evaluation-mode-default-requirements |
| 53 | + └ GET https://graph.microsoft.com/v1.0/teams/*/channels/getAllMessages |
| 54 | +``` |
| 55 | + |
| 56 | +#### Using the API with an invalid payment model |
| 57 | + |
| 58 | +- The 'More info' is coming from the `billingInformation` property. |
| 59 | + |
| 60 | +```shell |
| 61 | +[ REQUEST ] GET hhttps://graph.microsoft.com/v1.0/teams/*/channels/getAllMessages?model=randomModel |
| 62 | +[ API ] ┌ Passed through |
| 63 | + └ GET https://graph.microsoft.com/v1.0/teams/*/channels/getAllMessages?model=randomModel |
| 64 | +[ WARNING ] ┌ You are using a metered API with an invalid a payment model parameter (`randomModel`). |
| 65 | + │ More info at https://learn.microsoft.com/en-us/graph/teams-licenses#payment-models |
| 66 | + └ GET https://graph.microsoft.com/v1.0/teams/*/channels/getAllMessages |
| 67 | +``` |
| 68 | + |
| 69 | +### Random Errors |
| 70 | + |
| 71 | +- When registered, the plugin randomly generates 3 new HTTP 402 errors. |
| 72 | +- The `--failure-rate` should be the same that the one provided on the `GraphRandomErrorPlugin`. |
| 73 | +- 402s are dependent on the HTTP Verb that is used. In the configuration file, HTTP Verbs need to be explicit. |
| 74 | +- 402s should only be returned for the metered endpoints and only for the HTTP Verb used. |
| 75 | +- The list of 402s is available [here](https://learn.microsoft.com/en-us/graph/teams-licenses#payment-related-errors): |
| 76 | + |
| 77 | +| Error code | Scenario | HTTP Verb | Sample error message | |
| 78 | +| :--------------------- | :----------------------------------------------- | :----------- | :-------------------------------------------------------------------------------------------------------- | |
| 79 | +| 402 (Payment Required) | Passing `model=A` without a Microsoft E5 license | GET | `...needs a valid license to access this API...`, `...tenant needs a valid license to access this API...` | |
| 80 | +| 402 (Payment Required) | Calling Patch API passing `model=B` | PATCH | `...query parameter 'model' does not support value 'B' for this API. Use billing model 'A'...` | |
| 81 | +| 402 (Payment Required) | `Evaluation mode` capacity exceeded | GET or PATCH | `...evaluation mode capacity has been exceeded. Use a valid billing model...` | |
| 82 | + |
| 83 | +> **Note** |
| 84 | +> Full error messages are currently not available and we don't have specific information on the ODSP HTTP Errors yet. When we will get them, we will update the plugin to include them. |
| 85 | +
|
| 86 | +#### Payment Required |
| 87 | + |
| 88 | +```shell |
| 89 | +[ REQUEST ] GET https://graph.microsoft.com/v1.0/teams/*/channels/getAllMessages?model=A |
| 90 | +[ CHAOS ] ┌ 402 PaymentRequired (Needs a valid license to access this API) |
| 91 | + └ GET https://graph.microsoft.com/v1.0/teams/*/channels/getAllMessages?model=A |
| 92 | +``` |
| 93 | + |
| 94 | +## Configuration file |
| 95 | + |
| 96 | +The plugin will have its own preset file. This configuration file is where metered APIs will be listed. This file should have default values for all supported Microsoft Graph clouds. As of today, only the commercial cloud supports Metered APIs. |
| 97 | + |
| 98 | +- Each `urlToWatch` are rolled up to a single metered API. Multiple `urlToWatch` value means each endpoint behaves the same and should be treated as a metered API. |
| 99 | +- `supportedPaymentModels` are query string passed to the endpoint. If not present, they are considered in Evaluation Mode. If present, they need to be available in the `supportedPaymentModels` list. |
| 100 | +- `registrationForm` represents an URL to request access to the API (if any). |
| 101 | +- `httpVerbs` represents an array of HTTP Verbs that are effectively metered. If none are provided, we assume GET. |
| 102 | +- `registrationForm` represents an URL to request access to the API (if any). |
| 103 | + |
| 104 | +```json |
| 105 | +{ |
| 106 | + "plugins": [ |
| 107 | + { |
| 108 | + "name": "GraphMeteredGuidancePlugin", |
| 109 | + "enabled": true, |
| 110 | + "pluginPath": "GraphProxyPlugins\\msgraph-developer-proxy-plugins.dll", |
| 111 | + "configSection": "graphMeteredGuidancePlugin" |
| 112 | + } |
| 113 | + ], |
| 114 | + "graphMeteredGuidancePlugin": [ |
| 115 | + { |
| 116 | + "urlsToWatch": [ |
| 117 | + "https://graph.microsoft.com/*/users/*/chats/getAllMessages" |
| 118 | + ], |
| 119 | + "supportedPaymentModels": ["model=A", "model=B"], |
| 120 | + "billingInformation": "https://learn.microsoft.com/en-us/graph/teams-licenses", |
| 121 | + "registrationForm": "https://aka.ms/teamsgraph/requestaccess" |
| 122 | + }, |
| 123 | + { |
| 124 | + "urlsToWatch": [ |
| 125 | + "https://graph.microsoft.com/*/teams/*/channels/getAllMessages" |
| 126 | + ], |
| 127 | + "supportedPaymentModels": ["model=A", "model=B"], |
| 128 | + "billingInformation": "https://learn.microsoft.com/en-us/graph/teams-licenses", |
| 129 | + "registrationForm": "https://aka.ms/teamsgraph/requestaccess" |
| 130 | + }, |
| 131 | + { |
| 132 | + "urlsToWatch": [ |
| 133 | + "https://graph.microsoft.com/*/teams/*/channels/*/messages/*", |
| 134 | + "https://graph.microsoft.com/*/teams/*/channels/*/messages/*/replies/*", |
| 135 | + "https://graph.microsoft.com/*/chats/*/messages/{message-id}*" |
| 136 | + ], |
| 137 | + "httpVerbs": ["PATCH"], |
| 138 | + "supportedPaymentModels": ["model=A"], |
| 139 | + "billingInformation": "https://learn.microsoft.com/en-us/graph/teams-licenses", |
| 140 | + "registrationForm": "https://aka.ms/teamsgraph/requestaccess" |
| 141 | + }, |
| 142 | + { |
| 143 | + "urlsToWatch": [ |
| 144 | + "https://graph.microsoft.com/v1.0/*/assignSensitivityLabel", |
| 145 | + "https://graph.microsoft.com/beta/*/assignSensitivityLabel" |
| 146 | + ], |
| 147 | + "httpVerbs": ["POST"], |
| 148 | + "registrationForm": "https://aka.ms/PreviewSPOPremiumAPI" |
| 149 | + } |
| 150 | + ] |
| 151 | +} |
| 152 | +``` |
0 commit comments