Email from Azure Functions (secure way)
Azure Functions - очень удобный инструмент для автоматизации каких-либо задач. Как-только автоматизация настроена - сразу возникает вопрос: как получать уведомления о результатах? Самое логичное решение - использовать электронную почту для отправки оповещений.
Как делать это безопасно и бесплатно расскажу ниже.
Подсказка : данный мануал можно использовать не только для отправки почты, но и впринципе для безопасной работы с любыми секретами/сертификатами/ключами.
Постановка задачи
Пускай у нас уже есть:
- Function App с именем “test-azurefunctions-notifications”
- Учётная запись от почтового сервера (пускай будет Office 365)
Сделаем так, чтобы мы могли:
- Отправлять уведомления из Function App
- Не хардкодить учётку в коде Function App
Все настройки можно выполнить при помощи Azure Portal.
Настройка Function App
Открываем:Function App - > Platform features -> NETWORKING -> Managed service identity
Включаем “Register with Azure Active Directory”
Это позволить приложению запрашивать access token для получения доступа к другим ресурсам Azure (в нашем случае Key Vault). Подробнее тут.
Настройка Azure Key Vault
Создаём Key Vault по инструкции. Добавляем логин и пароль от почтового аккаунта.
Key vault - > Secrets -> Generate/Import
Разрешаем нашему Function App запрашивать эти логин и пароль. Для этого идём в **Key vault - > Access policies -> Add new **и выбираем:
- Secret permissions : Get, List
- Select principal : test-azurefunctions-notifications
Отправка уведомлений
Проверим, что мы можем использовать сохранённые учётные данные.
Приведу вариант реализации на PowerShell. Примеры для других языков можно посмотреть в документации Microsoft.
Результат будет выглядеть примерно так:
Код на PowerShell.
#Email settings
$SendTo = "YOUR_EMAIL"
$Subj = "Hello from Azure Function"
$SMTPserver = "smtp.office365.com"
$SMTPPort = "587"
$VaultURI = "https://YOUR.vault.azure.net/"
$SenderLoginName = "YOUR-sender-ofice365-login" #How it's called in the Key Vault
$SenderPasswordName = "YOUR-sender-ofice365-password" #How it's called in the Key Vault
#Function: get Key Vault access token
function Get-AccessTokenKeyVault
{
$ResourceURI = "https://vault.azure.net"
$ApiVersion = "2017-09-01"
$TokenAuthURI = $env:MSI_ENDPOINT + "?resource=$ResourceURI&api-version=$ApiVersion"
$TokenResponse = Invoke-RestMethod -Method Get -Headers @{"Secret"="$env:MSI_SECRET"} -Uri $TokenAuthURI
$TokenResponse.access_token
}
#Function: get Key Vault secret
function Get-KeyVaultSecret
{
Param(
[string] $AccessTokenKeyVault,
[string] $SecretName
)
$ResourceURI = $VaultURI
$Uri = $ResourceURI + "secrets/$SecretName/?api-version=2016-10-01"
$keysResponse = Invoke-RestMethod -Method Get -Headers @{Authorization="Bearer $AccessTokenKeyVault"} -Uri $Uri
$keysResponse
}
function Send-Result
{
Param(
$Body
)
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $From, $($Password | ConvertTo-SecureString -AsPlainText -Force)
Send-MailMessage –From $From –To $SendTo –Subject $Subj –Body $Body -SmtpServer $SMTPserver -Credential $Credentials -UseSsl -Port $SMTPPort
}
#Obtain secrets
$AccessTokenKeyVault = Get-AccessTokenKeyVault
$From = (Get-KeyVaultSecret -AccessToken $AccessTokenKeyVault -SecretName $SenderLoginName).value
$Password = (Get-KeyVaultSecret -AccessToken $AccessTokenKeyVault -SecretName $SenderPasswordName).value
#Send email
Send-Result -Body "This is test from Function App at $(Get-Date)"