Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Azure EventHub provider #191

Merged
merged 9 commits into from
May 6, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions api/v1beta1/provider_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const (
// ProviderSpec defines the desired state of Provider
type ProviderSpec struct {
// Type of provider
// +kubebuilder:validation:Enum=slack;discord;msteams;rocket;generic;github;gitlab;bitbucket;azuredevops;googlechat;webex;sentry
// +kubebuilder:validation:Enum=slack;discord;msteams;rocket;generic;github;gitlab;bitbucket;azuredevops;googlechat;webex;sentry;azureeventhub;
// +required
Type string `json:"type"`

Expand Down Expand Up @@ -64,18 +64,19 @@ type ProviderSpec struct {
}

const (
GenericProvider string = "generic"
SlackProvider string = "slack"
DiscordProvider string = "discord"
MSTeamsProvider string = "msteams"
RocketProvider string = "rocket"
GitHubProvider string = "github"
GitLabProvider string = "gitlab"
BitbucketProvider string = "bitbucket"
AzureDevOpsProvider string = "azuredevops"
GoogleChatProvider string = "googlechat"
WebexProvider string = "webex"
SentryProvider string = "sentry"
GenericProvider string = "generic"
SlackProvider string = "slack"
DiscordProvider string = "discord"
MSTeamsProvider string = "msteams"
RocketProvider string = "rocket"
GitHubProvider string = "github"
GitLabProvider string = "gitlab"
BitbucketProvider string = "bitbucket"
AzureDevOpsProvider string = "azuredevops"
GoogleChatProvider string = "googlechat"
WebexProvider string = "webex"
SentryProvider string = "sentry"
AzureEventHubProvider string = "azureeventhub"
)

// ProviderStatus defines the observed state of Provider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ spec:
- googlechat
- webex
- sentry
- azureeventhub
type: string
username:
description: Bot username for this provider
Expand Down
82 changes: 81 additions & 1 deletion docs/spec/v1beta1/provider.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Notification providers:
* Google Chat
* Webex
* Sentry
* AzureEventHub
NissesSenap marked this conversation as resolved.
Show resolved Hide resolved
* Generic webhook

Git commit status providers:
Expand Down Expand Up @@ -106,7 +107,7 @@ kubectl create secret generic webhook-url \

Note that the secret must contain an `address` field.

The provider type can be: `slack`, `msteams`, `rocket`, `discord`, `googlechat`, `webex`, `sentry`, `github`, `gitlab`, `bitbucket`, `azuredevops` or `generic`.
The provider type can be: `slack`, `msteams`, `rocket`, `discord`, `googlechat`, `webex`, `sentry`, `azureeventhub`, `github`, `gitlab`, `bitbucket`, `azuredevops` or `generic`.

When type `generic` is specified, the notification controller will post the
incoming [event](event.md) in JSON format to the webhook address.
Expand Down Expand Up @@ -222,3 +223,82 @@ SECRET_NAME=tls-certs
kubectl create secret generic $SECRET_NAME \
--from-file=caFile=ca.crt
```

### Azure EventHub
NissesSenap marked this conversation as resolved.
Show resolved Hide resolved

The Azure EventHub supports two authentication methods, [JWT](https://docs.microsoft.com/en-us/azure/event-hubs/authenticate-application) and [SAS](https://docs.microsoft.com/en-us/azure/event-hubs/authorize-access-shared-access-signature) based.
NissesSenap marked this conversation as resolved.
Show resolved Hide resolved

#### JWT based auth

In JWT we use 3 input values.

Channel, token and address. We perform the follow translation to match we the data we need to communicate with Azure EventHub.
NissesSenap marked this conversation as resolved.
Show resolved Hide resolved

* channel = Azure EventHub namespace
* address = Azure EventHub name
* token = JWT

```yaml
apiVersion: notification.toolkit.fluxcd.io/v1beta1
kind: Provider
metadata:
name: azureeventhub
spec:
type: azureeventhub
channel: fluxv2
secretRef:
name: webhook-url
NissesSenap marked this conversation as resolved.
Show resolved Hide resolved
```

Notification controller don't take any responsibility for the JWT token to be updated.
NissesSenap marked this conversation as resolved.
Show resolved Hide resolved
You need to use a secondary tool to make sure that the token in the secret is renewed.

If you want to make a easy test assuming that you have setup a Azure Enterprise application and you called it event-hub you can follow most of the bellow commands.
You will need to provide the client_secret that you got when generating the Azure Enterprise Application.

```shell
export AZURE_CLIENT=$(az ad app list --filter "startswith(displayName,'event-hub')" --query '[].appId' |jq -r '.[0]')
export AZURE_SECRET='secret-client-secret-generated-at-creation'
export AZURE_TENANT=$(az account show -o tsv --query tenantId)

curl -X GET --data 'grant_type=client_credentials' --data "client_id=$AZURE_CLIENT" --data "client_secret=$AZURE_SECRET" --data 'resource=https://eventhubs.azure.net' -H 'Content-Type: application/x-www-form-urlencoded' https://login.microsoftonline.com/$AZURE_TENANT/oauth2/token |jq .access_token

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will use your account instead of the application account. Risk of giving to much access, I would recomend to use this way.

```

Use the output you got from the curl and add it to your secret like bellow.

```shell
kubectl create secret generic webhook-url \
--from-literal=address="fluxv2" \
--from-literal=token='A-valid-JWT-token'
```

#### SAS based auth

In SAS we only use the `address`field in the secret.

```yaml
apiVersion: notification.toolkit.fluxcd.io/v1beta1
kind: Provider
metadata:
name: azureeventhub
spec:
type: azureeventhub
secretRef:
name: webhook-url
NissesSenap marked this conversation as resolved.
Show resolved Hide resolved
```

Assuming that you have created Azure eventhub and namespace you should be able to use a similar command to get your connection string.
This will give you the default Root SAS, it's NOT supposed to be used in production.

```shell
az eventhubs namespace authorization-rule keys list --resource-group <rg-name> --namespace-name <namespace-name> --name RootManageSharedAccessKey -o tsv --query primaryConnectionString
# The output should look something like this:
Endpoint=sb://fluxv2.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yoursaskeygeneatedbyazure
```

To create the needed secret:

```shell
kubectl create secret generic webhook-url \
--from-literal=address="Endpoint=sb://fluxv2.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yoursaskeygeneatedbyazure"
```
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,21 @@ go 1.15
replace github.com/fluxcd/notification-controller/api => ./api

require (
github.com/Azure/azure-amqp-common-go/v3 v3.1.0
github.com/Azure/azure-event-hubs-go/v3 v3.3.7
github.com/Azure/azure-sdk-for-go v53.4.0+incompatible // indirect
github.com/Azure/go-amqp v0.13.6 // indirect
github.com/fluxcd/notification-controller/api v0.13.0
github.com/fluxcd/pkg/apis/meta v0.9.0
github.com/fluxcd/pkg/runtime v0.11.0
github.com/getsentry/sentry-go v0.10.0
github.com/go-logr/logr v0.3.0
github.com/google/go-github/v32 v32.1.0
github.com/hashicorp/go-retryablehttp v0.6.8
github.com/jpillora/backoff v1.0.0 // indirect
github.com/ktrysmt/go-bitbucket v0.6.5
github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/onsi/ginkgo v1.14.1
github.com/onsi/gomega v1.10.2
github.com/sethvargo/go-limiter v0.6.0
Expand All @@ -22,6 +28,8 @@ require (
github.com/stretchr/testify v1.6.1
github.com/whilp/git-urls v1.0.0
github.com/xanzy/go-gitlab v0.38.2
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect
golang.org/x/net v0.0.0-20210427231257-85d9c07bbe3a // indirect
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
k8s.io/api v0.20.4
k8s.io/apimachinery v0.20.4
Expand Down
Loading