A tool to renew e5 subscription by calling msgraph APIs
-
Create Application
See Register Application and Configure Permissions for more info. We need
tenant id,client idandclient secretof your application to access msgraph APIs. -
Create User Secrer File
Copy
user-secret.json.exampletouser-secret.json, edit it as your need. You can always add more credentials.If you want to use certificate instead secret, which is better for security, you can write a
certificatekey with path to your certificate file insteadsecretkey. If we find you setcertificate, it will always be used insteadsecret.Tips for people who prefer certificate instead secret:
-
If you add certificate after created application and added secret, the
client_idmay be changed so please update it. -
Using pfx format to this tool is tested. But you only need to upload public key part(*.crt) to Azure.
-
If your certificate has a password, you can create a
passwordskey in user secret file like this:{ "passwords": { "<sha512sum>": "<password>" } }<sha512sum>is the sha512 sum of the certificate file in lower case and<password>is its password in plain, please keep the configuration in secret to avoid someone using your certificate without being permitted.
Setting days is needed to be cautious, as it means
DayOfWeekin program, check here to find out its correct value. -
Tip
We support json, yaml and toml formats for now, althouth we use json as an example, you can always use other formats. The formats supported by us can even be extended by using modules
-
Install .NET
See here for more info, we need .NET 8 and later.
-
Get program
-
Run program
Simply run
./E5Renewerin binaries folder with arguments needed.Here are supported arguments:
--systemd: If runs in systemd environment, most of the time you should not need it.--user-secret: The path to the user secret file.--token: The string to access json api.--token-file: The file which first line is used as the token.--listen-unix-socket-permission: The permission to the unix domain socket file.- All AspNet.Core supported arguments. See here for more info.
We will listen on endpoint
http://127.0.0.1:5000by default, this is the default value of Asp.Net Core.Asp.Net Core supports
--urlsparameter to set customized listen endpoint, such as--urls=http://127.0.0.1:5001or--urls=http://unix:/path/to/socket. Unix Domain Socket file's permission can be customized with argument--listen-unix-socket-permission.Those customized arguments are actually Asp.Net Core configuration items, items' names are the TitleCase of arguments. For example,
--tokenwill be mapped toToken,--user-secretwill be mapped toUserSecret, and--listen-unix-socket-permissionwill be mapped toListenUnixSocketPermission. With this converting map, you can use Asp.Net Core's ways to provide them, such as json configuration, environment variable, etc. But there is a special case:--systemdshould be provided withSystemd=trueif you do not use commandline argument, as Asp.Net Core's configuration requires a value, we added a special check for the--systemdflag. Those customized arguments do not have short forms like-s,-u.--user-secretis required to be provided through any method to provide an Asp.Net Core configuration value, or aNullReferenceExceptionofuserSecretwill be thown.
Note
If --token and --token-file both are specified, we prefer --token. If you forget to set neither of them, we use a randomly generated value.
You can find it out in log output after sending any request to the program and meeting an authentication error.
Important
If you want to set unix socket permission, you have to write its actual value instead octal format. For example, using 511 instead 777 is required.
Run dotnet publish -c Release and you can get binary at E5Renewer/bin/Release/net8.0/publish
Tip
You can pass -p:E5RenewerAot=true to create an AoT build.
Using curl or any tool which can send http request, send request to endpoints like http://127.0.0.1:5000 or unix socket /path/to/socket,
each request should be sent with header Authorization: Bearer <auth_token>.
You will get json response if everything is fine. If it is a GET request, send milisecond timestamp in query param timestamp,
If it is a POST request, send milisecond timestamp in post json with key timestamp and convert it to string.
Most of the time, we will return json instead plain text, but you need to check response code to see if request is success.
If you are using https, simply send https request instead.
For example:
HTTP API for /v1/list_apis
curl -H 'Authorization: Bearer <auth_token>' -H 'Accept: application/json' \
'http://127.0.0.1:5000/v1/list_apis?timestamp=<timestamp>' | jq '.'
{
"method": "list_apis",
"args": {},
"result": [
"AgreementAcceptances.Get",
"Admin.Get",
"Agreements.Get",
"AppCatalogs.Get",
"ApplicationTemplates.Get",
"Applications.Get",
"AuditLogs.Get",
"AuthenticationMethodConfigurations.Get",
"AuthenticationMethodsPolicy.Get",
"CertificateBasedAuthConfiguration.Get",
"Chats.Get", "Communications.Get",
"Compliance.Get",
"Connections.Get",
"Contacts.Get",
"DataPolicyOperations.Get",
"DeviceAppManagement.Get",
"DeviceManagement.Get",
"Devices.Get",
"Direcory.Get",
"DirectoryObjects.Get",
"DirectoryRoleTemplates.Get",
"DirectoryRoles.Get",
"DomainDnsRecords.Get",
"Domains.Get",
"Drives.Get",
"Education.Get",
"EmployeeExperience.Get",
"External.Get",
"FilterOperators.Get",
"Functions.Get",
"GroupLifecyclePolicies.Get",
"GroupSettingTemplates.Get",
"GroupSetings.Get",
"Groups.Get",
"Identity.Get",
"IdentityGovernance.Get",
"IdentityProtection.Get",
"IdentityProviders.Get",
"InfomationProtecion.Get",
"Invitations.Get",
"OAuth2PermissionGrants.Get",
"Organization.Get",
"PermissionGrants.Get",
"Places.Count.Get",
"Places.GraphRoom.Get",
"Planner.Get",
"Policies.Get",
"Print.Get",
"Privacy.Get",
"Reports.Get",
"RoleManagement.Get",
"SchemaExtensions.Get",
"ScopedRoleMemberships.Get",
"Search.Get",
"Security.Get",
"ServicePrincipals.Get",
"Shares.Get",
"Sites.Get",
"Solutions.Get",
"SubscribedSkus.Get",
"Subscriptions.Get",
"Teams.Get",
"TeamsTemplates.Get",
"Teamwork.Get",
"TenantRelationships.Get",
"Users.Get"
],
"timestamp": "<timestamp_returned_by_server>"
}
Server will only accept request less than 30 seconds older than server time.
See http-api.md for possible apis
We have created a module system to extend the program, you can check modules.md for more info.