I have the following error when I start the masstransit with azure bus.Start(); on my function StartService() I have configuring my azure with masstransit and autofact. The error:
MassTransit.Azure.ServiceBus.Core.ServiceBusConnectionException
HResult=0x80131500
Message=ReceiveTransport faulted: sb://softbaire-amilkar.servicebus.windows.net/;SharedAccessKeyName=**REMOVED**;SharedAccessKey=**REMOVED**/TeamTimeManager
Source=mscorlib
configuration with masstransit:
public static IContainer ConfigureContainer()
{
var builder = new ContainerBuilder();
builder.AddMassTransit(cfg =>
{
cfg.SetKebabCaseEndpointNameFormatter();
cfg.AddConsumer<TeamTimeManager>();
cfg.UsingAzureServiceBus((context, conf) =>
{
var settings = new HostSettings
{
ServiceUri = new Uri("sb://softbaire-amilkar.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=UeIC0z5RPCt25SjnWdss2ssP5a6msUKNJxmLnBpm26g="),
TokenProvider = TokenProvider.CreateManagedIdentityTokenProvider()
};
conf.Host(settings);
conf.ConfigureEndpoints(context);
});
});
return builder.Build();
}
this is where I start the service and I get the error:
public void StartService()
{
var container = CreatorContainer.ConfigureContainer();
var bus = container.Resolve<IBusControl>();
if (host != null)
{
host.Close();
}
host = new ServiceHost(typeof(TeamTimeManager));
utilHost = new ServiceHost(typeof(TeamTimeUtilityManager));
bus.Start();
source.TraceInformation("Starting TeamTimeManager Azure Bus...");
host.Open();
source.TraceInformation("TeamTimeManager Started!");
utilHost.Open();
utilSource.TraceInformation("Starting TeamTimeUtilityManager...");
}
UPDATE
this problem is solved when I comment on the line:
cfg.AddConsumer<TeamTimeManager>();
if I add a queue or a subscription the problem appears again
BUG
https://github.com/Azure/azure-sdk-for-net/issues/8627
It's likely permissions. MassTransit requires Manage, and you're configuring the managed identity token provider.
Remove the shared access credentials from the connection string, since they would conflict with the managed identity provider.
Make sure the service identity has Manage permissions on the namespace.
Well, the problem was in the token provider.
The problem was that the token generated was connected to azure but without any queue or topic register, the problem started when I wanted to register queues and topics, when I wanted to generate the connection with the queue or a topic I got an error because the token was invalid for my user(weird), so... I changed the method to generate the token and everything started to work correctly.
Before:
var settings = new HostSettings
{
ServiceUri = new Uri("sb://xxxx-busazure.servicebus.windows.net"),
TokenProvider = TokenProvider.CreateManagedIdentityTokenProvider()
};
After: now I'm using CreateSharedAccessSignatureTokenProvider() you need to send as parameters the "SharedAccessKeyName" and the "SharedAccessKey"
var settings = new HostSettings
{
ServiceUri = new Uri("sb://xxxxx-busazure.servicebus.windows.net"),
TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", "xxxxxxxxxxxxxxx=")
};
queues and everything is running smoothly, Final configuration method:
public static IContainer ConfigureContainer()
{
var builder = new ContainerBuilder();
builder.AddMassTransit(cfg =>
{
cfg.SetKebabCaseEndpointNameFormatter();
cfg.AddServiceBusMessageScheduler();
cfg.AddConsumer<TeamTimeManager>();
cfg.UsingAzureServiceBus((context, conf) =>
{
conf.UseServiceBusMessageScheduler();
var settings = new HostSettings
{
ServiceUri = new Uri("sb://amilkar-busazure.servicebus.windows.net"),
TokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", "xxxxxxxxxxxxxxxxxxxxxx")
};
conf.Host(settings);
conf.ReceiveEndpoint("team-time-manager", e =>
{
e.ConfigureConsumer<TeamTimeManager>(context);
});
conf.ConfigureEndpoints(context);
});
});
return builder.Build();
}
Related
I currently have a DotNet Core app that's requiring a users x509 Certificate. I currently can pull it and validate it with the following
In my Program.cs
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
webBuilder.ConfigureKestrel(o =>
{
o.ConfigureHttpsDefaults(o =>
o.ClientCertificateMode = ClientCertificateMode.RequireCertificate);
});
});
In my Startup.cs
services.AddScoped<CertificateValidationService>();
services.AddControllers();
services.AddAuthentication(
CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.AllowedCertificateTypes = CertificateTypes.All;
options.Events = new CertificateAuthenticationEvents
{
OnAuthenticationFailed = context =>
{
context.NoResult();
context.Response.Headers.Add("Token-Expired", "true");
context.Response.ContentType = "text/plain";
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
return Task.CompletedTask;
},
OnCertificateValidated = context =>
{
var validationService =
context.HttpContext.RequestServices
.GetRequiredService<CertificateValidationService>();
if (validationService.ValidateCertificate(
context.ClientCertificate))
{
var claims = new[]
{
new Claim(
ClaimTypes.NameIdentifier,
context.ClientCertificate.Subject,
ClaimValueTypes.String,
context.Options.ClaimsIssuer),
new Claim(
ClaimTypes.Name,
context.ClientCertificate.Subject,
ClaimValueTypes.String,
context.Options.ClaimsIssuer)
};
context.Properties.SetParameter("x509", context.ClientCertificate);
context.Principal = new ClaimsPrincipal(
new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
}
else
{
context.Fail($"Unrecognized client certificate: " +
$"{context.ClientCertificate.GetNameInfo(X509NameType.SimpleName, false)}");
}
return Task.CompletedTask;
}
};
});
services.AddControllers();
I also have my Implementation for verifying the cert and that works fine. However, later in the application I want to do the following
[Route("/signature")]
[HttpGet]
public string Signature()
{
using (var signer = new PdfDocumentSigner(#"C:\test\Document.pdf"))
{
ITsaClient tsaClient = new TsaClient(new Uri(#"https://freetsa.org/tsr"),
DevExpress.Office.DigitalSignatures.HashAlgorithmType.SHA256);
string signatureName = signer.GetSignatureFieldNames(false)[0];
// Create a provider that retrieves certificates from a store:
// public CertificateStoreProvider(X509Certificate2Collection collection);
using (var certificateStoreProvider =
new CertificateStoreProvider(new X509Store(StoreLocation.CurrentUser), true))
{
// Add the signature to the security store
// and specify the CrlClient and OcspClient objects
// used to check the certificates' revocation status:
signer.AddToDss(signatureName, new CrlClient(), new OcspClient(), certificateStoreProvider);
}
signer.SaveDocument(#"C:\test\signedLTV.pdf", new[] { new PdfSignatureBuilder(new PdfTimeStamp(tsaClient)) });
}
return "The file was signed";
}
Now obviously the problem is that this is the X509 Certificate on my Local Host. BUT what I want to do is use the one that the user validated with which was passed along in the Program/Startup
Is there a way I can programmatically get that or pass that along safely?
You can't do this. In order to use client certificate for subsequent cryptographic operations (like signing or decryption), you need a client's private key. However, client never sends its private key. Client's private key must never leave client machine. Your entire approach is non-working. Here is the relevant thread with a bit deeper explanation: Open X509 Certificates Selection Using USB Token in C# Hosted on IIS
What you can do is to move signing process to client side (execute in browser), but this approach has its own issues, like you will have to download entire PDF to client browser, sign somehow and then upload back to server.
My ConfigureService method in startup.cs class
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddNewtonsoftJson();
services.AddSingleton<IConfiguration>(this.Configuration);
// Load settings
var settings = new BotSettings();
Configuration.Bind(settings);
services.AddDbContext<BotDbContext>(options => options.UseSqlServer(settings.ConnectionString));
// Create the credential provider to be used with the Bot Framework Adapter.
services.AddSingleton<ICredentialProvider, ConfigurationCredentialProvider>();
services.AddSingleton<BotAdapter>(sp => (BotFrameworkHttpAdapter)sp.GetService<IBotFrameworkHttpAdapter>());
// Register AuthConfiguration to enable custom claim validation for skills.
services.AddSingleton(sp => new AuthenticationConfiguration { ClaimsValidator = new AllowedCallersClaimsValidator(settings.SkillConfiguration) });
// register components.
ComponentRegistration.Add(new DialogsComponentRegistration());
ComponentRegistration.Add(new DeclarativeComponentRegistration());
ComponentRegistration.Add(new AdaptiveComponentRegistration());
ComponentRegistration.Add(new LanguageGenerationComponentRegistration());
ComponentRegistration.Add(new QnAMakerComponentRegistration());
ComponentRegistration.Add(new LuisComponentRegistration());
// register Handoff
ConfigureHandOff(services, settings);
// This is for custom action component registration.
ComponentRegistration.Add(new CustomActionComponentRegistration());
// Register the skills client and skills request handler.
services.AddSingleton<SkillConversationIdFactoryBase, SkillConversationIdFactory>();
services.AddHttpClient<BotFrameworkClient, SkillHttpClient>();
services.AddSingleton<ChannelServiceHandler, SkillHandler>();
services.AddApplicationInsightsTelemetry(settings?.ApplicationInsights?.InstrumentationKey ?? string.Empty);
services.AddSingleton<ITelemetryInitializer, OperationCorrelationTelemetryInitializer>();
services.AddSingleton<ITelemetryInitializer, TelemetryBotIdInitializer>();
services.AddSingleton<IBotTelemetryClient, BotTelemetryClient>();
services.AddSingleton<TelemetryLoggerMiddleware>(sp =>
{
var telemetryClient = sp.GetService<IBotTelemetryClient>();
return new TelemetryLoggerMiddleware(telemetryClient, logPersonalInformation: settings?.Telemetry?.LogPersonalInformation ?? false);
});
services.AddSingleton<TelemetryInitializerMiddleware>(sp =>
{
var httpContextAccessor = sp.GetService<IHttpContextAccessor>();
var telemetryLoggerMiddleware = sp.GetService<TelemetryLoggerMiddleware>();
return new TelemetryInitializerMiddleware(httpContextAccessor, telemetryLoggerMiddleware, settings?.Telemetry?.LogActivities ?? false);
});
var storage = ConfigureStorage(settings);
services.AddSingleton(storage);
var userState = new UserState(storage);
var conversationState = new ConversationState(storage);
services.AddSingleton(userState);
services.AddSingleton(conversationState);
//Configure bot loading path
var botDir = settings.Bot;
var resourceExplorer = new ResourceExplorer().AddFolder(botDir);
var defaultLocale = Configuration.GetValue<string>("defaultLanguage") ?? "en-us";
var rootDialog = GetRootDialog(botDir);
services.AddSingleton(resourceExplorer);
resourceExplorer.RegisterType<OnQnAMatch>("Microsoft.OnQnAMatch");
services.AddSingleton<IBotFrameworkHttpAdapter, BotFrameworkHttpAdapter>(s =>
GetBotAdapter(storage, settings, userState, conversationState, s));
var removeRecipientMention = settings?.Feature?.RemoveRecipientMention ?? false;
//Adding Required Services
services.AddTransient(typeof(IRepository<>), typeof(Repository<>));
services.AddTransient<IUserService, UserService>();
services.AddTransient<ICommunicationService, CommunicationService>();
services.AddTransient<IMessageService, MessageService>();
services.AddSingleton<IBot>(s =>
new ComposerBot(
s.GetService<IUserService>(),
s.GetService<ConversationState>(),
s.GetService<UserState>(),
s.GetService<MessageRouter>(),
s.GetService<MessageRouterResultHandler>()));
}
However when I am trying to access UserService Object it passing null object in ComposerBot.cs class? What could be the reason?
public ComposerBot(
IUserService userService,
ConversationState conversationState,
UserState userState,
MessageRouter messageRouter,
MessageRouterResultHandler messageRouterResultHandler)
{
this.userService = userService; **showing NULL**
this.conversationState = conversationState;
this.userState = userState;
this.dialogState = conversationState.CreateProperty<DialogState>("DialogState");
this.messageRouter = messageRouter;
this.messageRouterResultHandler = messageRouterResultHandler;
}
I think you are running into this issue:
https://github.com/dotnet/aspnetcore/issues/28684.
this is related:
https://github.com/dotnet/aspnetcore/issues/17442
A tempory solution at least for me was to inject the service in a razor page to get the user there and pass the user to the service.
note: this should be a comment but i dont have enough repuation to comment.
I have implemented an yarp.reverse proxy server with the code below:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpProxy();
services.AddCors(options =>
{
options.AddPolicy("customPolicy", builder =>
{
builder.AllowAnyOrigin();
});
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHttpProxy httpProxy)
{
// Configure our own HttpMessageInvoker for outbound calls for proxy operations
var httpClient = new HttpMessageInvoker(new SocketsHttpHandler()
{
UseProxy = false,
AllowAutoRedirect = false,
AutomaticDecompression = DecompressionMethods.None,
UseCookies = false
});
// Setup our own request transform class
var transformer = new CustomTransformer(); // or HttpTransformer.Default;
var requestOptions = new RequestProxyOptions { Timeout = TimeSpan.FromSeconds(100) };
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.Map("/{**catch-all}", async httpContext =>
{
httpContext.Request.Headers["Connection"] = "upgrade";
await httpProxy.ProxyAsync(httpContext, "http://192.168.178.80:5000", httpClient, requestOptions, transformer);
var errorFeature = httpContext.Features.Get<IProxyErrorFeature>();
save_log(httpContext.Request.Path, "/", "http://192.168.178.80:5000" + httpContext.Request.Path, "3");
// Check if the proxy operation was successful
if (errorFeature != null)
{
var error = errorFeature.Error;
var exception = errorFeature.Exception;
}
});
});
}
And in another app a SignalR server following this example: https://learn.microsoft.com/en-GB/aspnet/core/tutorials/signalr?view=aspnetcore-5.0&tabs=visual-studio
The proxy server works and forwards the request to the signalR server. But the signalR Client is not able to connect to the signalR Server. I always get a Connection disconnected with error
Error: Server timeout elapsed without receiving a message from the server.
in the Java Script console.
But the SSE is connected as you can see in the following browser status report:
signalr.js:2156 [2021-03-25T13:19:29.970Z] Information: SSE connected to https://localhost:44318/chatHub?id=IqKD6P0NsUY9Is6OSrMusQ
The problem seems to be the Proxy Server because if I call the site directly it works. Has somebody any idea what's wrong with my Proxy and how I can solve it?
I am using RabbitMQ MassTransit for service bus implementation in my .Net core solution. I have created a queue by the name log.service. After lot many efforts I was finally able to push the messages in the queue and can see them in management tool but when I am listening to the same queue in another microservice project, I am unable to do so. I have pushed the messages in the bus from Authentication service and want to log the event in Logging service. Please help!
Here is my authentication-StartUp.cs
var buildr = new ContainerBuilder();
buildr.RegisterType<LoggingCommandConsumer>();
buildr.Register(c =>
{
return Bus.Factory.CreateUsingRabbitMq(sbc =>
{
var host = sbc.Host(new Uri("rabbitmq://localhost/"), h =>
{
h.Username("guest");
h.Password("guest");
});
sbc.ExchangeType = ExchangeType.Direct;
sbc.ReceiveEndpoint(host, "log.service", e =>
{
e.Consumer<LoggingCommandConsumer>();
});
});
})
.As<IBusControl>()
.As<IBus>()
.As<IPublishEndpoint>()
.SingleInstance();
buildr.Populate(services);
ApplicationContainer = buildr.Build();
return new AutofacServiceProvider(ApplicationContainer);
Here is my logging-StartUp.cs:
var buildr = new ContainerBuilder();
buildr.RegisterType<LoggingCommandConsumer>();
buildr.Register(context =>
{
var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
var host = cfg.Host(new Uri("rabbitmq://localhost/"), h =>
{
h.Username("guest");
h.Password("guest");
});
cfg.ReceiveEndpoint(host, "log.service", e =>
{
e.Consumer<LoggingCommandConsumer>();
});
});
return busControl;
})
.SingleInstance()
.As<IBusControl>()
.As<IBus>();
buildr.Populate(services);
ApplicationContainer = buildr.Build();
return new AutofacServiceProvider(ApplicationContainer);
Here I am starting the Bus in both the StartUp.CS
var bus = ApplicationContainer.Resolve<IBusControl>();
var busHandle = TaskUtil.Await(() => bus.StartAsync());
lifetime.ApplicationStopping.Register(() => busHandle.Stop());
Here I am sending the message to end points from authentication controller:
var sendToUri = new
Uri("rabbitmq://localhost/log.servicebind=true&queue=log.service");
var endPoint = await _bus.GetSendEndpoint(sendToUri);
await endPoint.Send<ILoggingCommand>(new
{
XCorrelationId = "asd",
M4SId = "M4SId",
Host = "asdasd",
Level = "Level",
Time = "2019-01-02T07:06:43.722Z",
Message = "Message",
Other = "Other"
});
return Ok();
When I try to get the above message in log.service bus in rabbitMQ management tool, I am able to do so...but not able to listen it in logging-startup.cs
Your endpoint has a queue defined by "log.service" + Guid.NewGuid().ToString() but you send messages to the log.service queue.
I don't really see the point of adding the guid to the endpoint address, what are you trying to achieve?
if you define your endpoint as cfg.ReceiveEndpoint(host, "log.service", ep => <configuration> it should work. You need to uncomment your consumer.
I am getting this error when hosting my application on azure:
The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread's user context, which may be the case when the thread is impersonating.
When trying creating a user or resending a confirmation email.
This article:
http://tech.trailmax.info/2014/06/asp-net-identity-and-cryptographicexception-when-running-your-site-on-microsoft-azure-web-sites/
says that you should create a single instance on the startup class, but I am using autofac, so I have done this:
builder.Register(c => new IdentityFactoryOptions<UserProvider>() { DataProtectionProvider = new DpapiDataProtectionProvider(c.Resolve<PiiiCKConfig>().Issuer) }).SingleInstance();
and then in my UserManager constructor, I do this:
// Get our data protection provider
var dataProtectionProvider = options.DataProtectionProvider;
// If we have on
if (dataProtectionProvider != null)
{
// Set our token provider
UserTokenProvider = new DataProtectorTokenProvider<User>(dataProtectionProvider.Create("PiiiK Identity"))
{
// Set our long the email confirmation token will last
TokenLifespan = TimeSpan.FromHours(6)
};
}
But I still get the error.
Does anyone know how I can solve this issue?
According to your description, I checked this issue on my side and I could reproduce this issue. Per my test, you could follow the approaches below to solve this issue:
builder.Register(c => new IdentityFactoryOptions<UserProvider>() { DataProtectionProvider = new DpapiDataProtectionProvider(c.Resolve<PiiiCKConfig>().Issuer) }).SingleInstance();
You could using IAppBuilder.GetDataProtectionProvider() instead of declaring a new DpapiDataProtectionProvider, based on the above code, you need to modify it as follows:
builder.Register(c => new IdentityFactoryOptions<UserProvider>()
{
DataProtectionProvider = app.GetDataProtectionProvider()
}).SingleInstance();
Or
builder.Register<IDataProtectionProvider>(c => app.GetDataProtectionProvider()).SingleInstance();
Additionally, here is a similar issue, you could refer to here.
UPDATE:
Here is the code snippet of Startup.Auth.cs as follows:
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.Register(c => new IdentityFactoryOptions<ApplicationUserManager>()
{
DataProtectionProvider = app.GetDataProtectionProvider()
}).SingleInstance();
//Or
//builder.Register<IDataProtectionProvider>(c =>app.GetDataProtectionProvider()).SingleInstance();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}