Merge pull request #446 from Azure/serkar.AddCustomRbacEhSample

Adding RBAC custom role sample
This commit is contained in:
Serkant Karaca 2019-07-02 14:29:03 -07:00 коммит произвёл GitHub
Родитель 37cf05a10e 333774188e
Коммит d47a55f3fe
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 253 добавлений и 1 удалений

Просмотреть файл

@ -15,7 +15,7 @@ namespace SampleEphReceiver
private const string StorageContainerName = "Storage account container name";
private const string StorageAccountName = "Storage account name";
private const string StorageAccountKey = "Storage account key";
private static readonly string StorageConnectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", StorageAccountName, StorageAccountKey);
public static void Main(string[] args)

Просмотреть файл

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<AssemblyName>CustomRole</AssemblyName>
<OutputType>Exe</OutputType>
<PackageId>CustomRole</PackageId>
<RuntimeFrameworkVersion>2.1.0</RuntimeFrameworkVersion>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.EventHubs" Version="4.0.0" />
<PackageReference Include="Microsoft.Azure.EventHubs.Processor" Version="4.0.0" />
<PackageReference Include="Microsoft.Azure.Storage.Blob" Version="9.4.2" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.0.0" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.10
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomRole", "CustomRole.csproj", "{679DFCC5-76BD-4725-A51E-AFBB01565401}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{679DFCC5-76BD-4725-A51E-AFBB01565401}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{679DFCC5-76BD-4725-A51E-AFBB01565401}.Debug|Any CPU.Build.0 = Debug|Any CPU
{679DFCC5-76BD-4725-A51E-AFBB01565401}.Release|Any CPU.ActiveCfg = Release|Any CPU
{679DFCC5-76BD-4725-A51E-AFBB01565401}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4190FE18-2881-43ED-9A45-6AECB8D3314A}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,95 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace CustomRole
{
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.EventHubs;
using Microsoft.Azure.EventHubs.Processor;
using Microsoft.Identity.Client;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
public class Program
{
private const string Authority = "Authority of tenant";
private const string ClientId = "AAD app id";
private const string ClientSecret = "AAD app secret";
private const string EventHubNamespace = "FQDN of Event Hubs namespace";
private const string EventHubName = "Event hub name";
private const string StorageAccountName = "Storage account name";
private const string StorageContainerName = "Storage account container name";
static IConfidentialClientApplication tokenClient;
public static async Task Main(string[] args)
{
// Use the same identity client for both Event Hubs and Storage
tokenClient = ConfidentialClientApplicationBuilder.Create(ClientId)
.WithAuthority(Authority)
.WithClientSecret(ClientSecret)
.Build();
// Create Storage client with access token provider
var tokenAndFrequency = await TokenRenewerAsync(tokenClient, CancellationToken.None);
var tokenCredential = new TokenCredential(tokenAndFrequency.Token,
TokenRenewerAsync,
tokenClient,
tokenAndFrequency.Frequency.Value);
var storageCredentials = new StorageCredentials(tokenCredential);
CloudStorageAccount cloudStorageAccount = new CloudStorageAccount(storageCredentials, StorageAccountName, string.Empty, true);
// Create Event Hubs access token provider and processor host
TokenProvider tp = TokenProvider.CreateAzureActiveDirectoryTokenProvider(
new AzureActiveDirectoryTokenProvider.AuthenticationCallback(GetAccessTokenAsync), Authority, tokenClient);
var eventProcessorHost = new EventProcessorHost(
new Uri(EventHubNamespace),
EventHubName,
PartitionReceiver.DefaultConsumerGroupName,
tp,
cloudStorageAccount,
StorageContainerName);
// Registers the Event Processor Host and starts receiving messages
Console.WriteLine("Registering EventProcessor...");
await eventProcessorHost.RegisterEventProcessorAsync<SimpleEventProcessor>();
Console.WriteLine("Receiving. Press enter key to stop worker.");
Console.ReadLine();
// Disposes of the Event Processor Host
await eventProcessorHost.UnregisterEventProcessorAsync();
}
private static async Task<NewTokenAndFrequency> TokenRenewerAsync(Object state, CancellationToken cancellationToken)
{
var authResult = await AcquireTokenAsync("https://storage.azure.com/");
// Renew the token 5 minutes before it expires.
var next = (authResult.ExpiresOn - DateTimeOffset.UtcNow) - TimeSpan.FromMinutes(5);
if (next.Ticks < 0)
{
next = default(TimeSpan);
Console.WriteLine("Renewing token...");
}
// Return the new token and the next refresh time.
return new NewTokenAndFrequency(authResult.AccessToken, next);
}
static async Task<string> GetAccessTokenAsync(string audience, string authority, object state)
{
var authResult = await AcquireTokenAsync(audience);
return authResult.AccessToken;
}
static async Task<AuthenticationResult> AcquireTokenAsync(string audience)
{
return await tokenClient
.AcquireTokenForClient(new string[] { $"{audience}/.default" }).ExecuteAsync();
}
}
}

Просмотреть файл

@ -0,0 +1,21 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CustomRole")]
[assembly: AssemblyTrademark("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("679dfcc5-76bd-4725-a51e-afbb01565401")]

Просмотреть файл

@ -0,0 +1,44 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace CustomRole
{
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Azure.EventHubs;
using Microsoft.Azure.EventHubs.Processor;
public class SimpleEventProcessor : IEventProcessor
{
public Task CloseAsync(PartitionContext context, CloseReason reason)
{
Console.WriteLine($"Processor Shutting Down. Partition '{context.PartitionId}', Reason: '{reason}'.");
return Task.CompletedTask;
}
public Task OpenAsync(PartitionContext context)
{
Console.WriteLine($"SimpleEventProcessor initialized. Partition: '{context.PartitionId}'");
return Task.CompletedTask;
}
public Task ProcessErrorAsync(PartitionContext context, Exception error)
{
Console.WriteLine($"Error on Partition: {context.PartitionId}, Error: {error.Message}");
return Task.CompletedTask;
}
public Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
{
foreach (var eventData in messages)
{
var data = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count);
Console.WriteLine($"Message received. Partition: '{context.PartitionId}', Data: '{data}', Partition Key: '{eventData.SystemProperties.PartitionKey}'");
}
return context.CheckpointAsync();
}
}
}

Просмотреть файл

@ -0,0 +1,45 @@
# Receive events with the Event Processor Host in .NET Standard with a custom role which grants Listen claim for Event Hubs and blob claims for Storage accounts.
## Prerequisites
* [Microsoft Visual Studio 2015 or 2017](http://www.visualstudio.com).
* [.NET Core Visual Studio 2015 or 2017 tools](http://www.microsoft.com/net/core).
* An Azure subscription.
* [An event hub namespace and an event hub](event-hubs-quickstart-namespace-portal.md).
* An Azure Storage account.
## Run the sample
To run the sample, follow these steps:
1. Clone or download this GitHub repo.
2. [Create an Event Hubs namespace and an event hub](https://docs.microsoft.com/azure/event-hubs/event-hubs-create).
3. Create a Storage account to host a blob container, needed for lease management by the Event Processor Host.
3. [Create a new custom role](https://docs.microsoft.com/en-us/azure/role-based-access-control/custom-roles) with the definition below.
4. [Create a new AAD (Azure Active Directory) application](https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal).
5. Assign AAD application to both Event Hubs namespace and Storage account with the custom role you just created.
```
{
"Name": "Custom role for RBAC sample",
"Id": "8ddab47f-cf99-4b04-8fc3-1d2d857fb931",
"Description": "Test role",
"IsCustom": true,
"Actions": [
"Microsoft.Storage/*"
],
"NotActions": [],
"DataActions": [
"Microsoft.EventHub/namespaces/messages/receive/action",
"Microsoft.Storage/*"
],
"NotDataActions": [],
"AssignableScopes": [
"/subscriptions/your-subscription-id"
]
}
```
6. Update the sample with Event Hubs namespace and Storage account name.
7. Run [Sender application](https://github.com/Azure/azure-event-hubs/tree/serkar.AddCustomRbacEhSample/samples/DotNet/Microsoft.Azure.EventHubs/SampleSender) to send some number of messages to your event hub.
8. Run the CustomRole sample to receive those events back.