diff --git a/src/Api/Startup.cs b/src/Api/Startup.cs index 7f77bcaeb4..af474d2060 100644 --- a/src/Api/Startup.cs +++ b/src/Api/Startup.cs @@ -14,13 +14,13 @@ using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.Net.Http.Headers; using Newtonsoft.Json.Serialization; using AspNetCoreRateLimit; -using Bit.Api.Middleware; using Serilog.Events; using Stripe; using Bit.Core.Utilities; using IdentityModel; using IdentityServer4.AccessTokenValidation; using jsreport.AspNetCore; +using Bit.Core.IdentityServer; namespace Bit.Api { diff --git a/src/Api/Utilities/TokenRetrieval.cs b/src/Core/IdentityServer/TokenRetrieval.cs similarity index 97% rename from src/Api/Utilities/TokenRetrieval.cs rename to src/Core/IdentityServer/TokenRetrieval.cs index fbfeec829d..b16708640d 100644 --- a/src/Api/Utilities/TokenRetrieval.cs +++ b/src/Core/IdentityServer/TokenRetrieval.cs @@ -2,7 +2,7 @@ using System; using System.Linq; -namespace Bit.Api.Utilities +namespace Bit.Core.IdentityServer { public static class TokenRetrieval { diff --git a/src/Api/Middleware/CurrentContextMiddleware.cs b/src/Core/Utilities/CurrentContextMiddleware.cs similarity index 97% rename from src/Api/Middleware/CurrentContextMiddleware.cs rename to src/Core/Utilities/CurrentContextMiddleware.cs index 346c30d38a..1b12ef5b4c 100644 --- a/src/Api/Middleware/CurrentContextMiddleware.cs +++ b/src/Core/Utilities/CurrentContextMiddleware.cs @@ -1,12 +1,11 @@ -using Bit.Core; -using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http; using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; -namespace Bit.Api.Middleware +namespace Bit.Core.Utilities { public class CurrentContextMiddleware { diff --git a/src/Events/Controllers/EventsController.cs b/src/Events/Controllers/EventsController.cs index 5cef2ef38a..637c2a1570 100644 --- a/src/Events/Controllers/EventsController.cs +++ b/src/Events/Controllers/EventsController.cs @@ -1,13 +1,45 @@ using System; +using System.Threading.Tasks; +using Bit.Core; +using Bit.Core.Repositories; +using Bit.Core.Services; +using Bit.Events.Models; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace Events.Controllers { + [Authorize("Application")] public class EventsController : Controller { - [HttpPost("~/")] - public void Post([FromBody]string value) + private readonly CurrentContext _currentContext; + private readonly IEventService _eventService; + private readonly ICipherRepository _cipherRepository; + + public EventsController( + CurrentContext currentContext, + IEventService eventService, + ICipherRepository cipherRepository) { + _currentContext = currentContext; + _eventService = eventService; + _cipherRepository = cipherRepository; + } + + [HttpPost("~/cipher/{id}")] + public async Task PostCipher(Guid id, [FromBody]EventModel model) + { + var cipher = await _cipherRepository.GetByIdAsync(id, _currentContext.UserId.Value); + if(cipher != null) + { + await _eventService.LogCipherEventAsync(cipher, model.Type); + } + } + + [HttpPost("~/user")] + public async Task PostUser([FromBody]EventModel model) + { + await _eventService.LogUserEventAsync(_currentContext.UserId.Value, model.Type); } } } diff --git a/src/Events/Events.csproj b/src/Events/Events.csproj index 91c4796c73..f430c78929 100644 --- a/src/Events/Events.csproj +++ b/src/Events/Events.csproj @@ -9,6 +9,7 @@ + @@ -17,4 +18,8 @@ + + + + diff --git a/src/Events/Models/EventModel.cs b/src/Events/Models/EventModel.cs new file mode 100644 index 0000000000..d75035ec98 --- /dev/null +++ b/src/Events/Models/EventModel.cs @@ -0,0 +1,10 @@ +using System; +using Bit.Core.Enums; + +namespace Bit.Events.Models +{ + public class EventModel + { + public EventType Type { get; set; } + } +} diff --git a/src/Events/Startup.cs b/src/Events/Startup.cs index e464b6af9e..6d905f0bed 100644 --- a/src/Events/Startup.cs +++ b/src/Events/Startup.cs @@ -1,36 +1,119 @@ -using System; +using System.Security.Claims; +using Bit.Core; +using Bit.Core.IdentityServer; +using Bit.Core.Services; +using Bit.Core.Utilities; +using IdentityModel; +using IdentityServer4.AccessTokenValidation; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Serilog.Events; namespace Bit.Events { public class Startup { - public Startup(IConfiguration configuration) + public Startup(IHostingEnvironment env, IConfiguration configuration) { Configuration = configuration; + Environment = env; } public IConfiguration Configuration { get; } + public IHostingEnvironment Environment { get; set; } public void ConfigureServices(IServiceCollection services) { // Options services.AddOptions(); + // Settings + var globalSettings = services.AddGlobalSettingsServices(Configuration); + + // Repositories + services.AddSqlServerRepositories(globalSettings); + + // Context + services.AddScoped(); + + // Identity + services + .AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) + .AddIdentityServerAuthentication(options => + { + options.Authority = globalSettings.BaseServiceUri.InternalIdentity; + options.RequireHttpsMetadata = !Environment.IsDevelopment() && + globalSettings.BaseServiceUri.InternalIdentity.StartsWith("https"); + options.NameClaimType = ClaimTypes.Email; + options.TokenRetriever = TokenRetrieval.FromAuthorizationHeaderOrQueryString( + new string[] { "Bearer", "Bearer3" }); + options.SupportedTokens = SupportedTokens.Jwt; + }); + + services.AddAuthorization(config => + { + config.AddPolicy("Application", policy => + { + policy.RequireAuthenticatedUser(); + policy.RequireClaim(JwtClaimTypes.AuthenticationMethod, "Application"); + }); + }); + + // Services + services.AddScoped(); + if(!globalSettings.SelfHosted && CoreHelpers.SettingHasValue(globalSettings.Storage.ConnectionString)) + { + services.AddSingleton(); + } + else + { + services.AddSingleton(); + } + // Mvc services.AddMvc(); } - public void Configure(IApplicationBuilder app, IHostingEnvironment env) + public void Configure( + IApplicationBuilder app, + IHostingEnvironment env, + ILoggerFactory loggerFactory, + IApplicationLifetime appLifetime, + GlobalSettings globalSettings) { + loggerFactory.AddSerilog(env, appLifetime, globalSettings, (e) => + { + var context = e.Properties["SourceContext"].ToString(); + if(context.Contains("IdentityServer4.Validation.TokenValidator") || + context.Contains("IdentityServer4.Validation.TokenRequestValidator")) + { + return e.Level > LogEventLevel.Error; + } + + return e.Level >= LogEventLevel.Error; + }); + if(env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } + // Default Middleware + app.UseDefaultMiddleware(env); + + // Add Cors + app.UseCors("All"); + + // Add authentication to the request pipeline. + app.UseAuthentication(); + + // Add current context + app.UseMiddleware(); + + // Add MVC to the request pipeline. app.UseMvc(); } } diff --git a/src/Events/appsettings.Development.json b/src/Events/appsettings.Development.json deleted file mode 100644 index fa8ce71a97..0000000000 --- a/src/Events/appsettings.Development.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Logging": { - "IncludeScopes": false, - "LogLevel": { - "Default": "Debug", - "System": "Information", - "Microsoft": "Information" - } - } -} diff --git a/src/Events/appsettings.Preview.json b/src/Events/appsettings.Preview.json new file mode 100644 index 0000000000..ebe1db52d5 --- /dev/null +++ b/src/Events/appsettings.Preview.json @@ -0,0 +1,10 @@ +{ + "globalSettings": { + "baseServiceUri": { + "vault": "https://preview-vault.bitwarden.com", + "api": "https://preview-api.bitwarden.com", + "identity": "https://preview-identity.bitwarden.com", + "internalIdentity": "https://preview-identity.bitwarden.com" + } + } +} diff --git a/src/Events/appsettings.Production.json b/src/Events/appsettings.Production.json new file mode 100644 index 0000000000..87ace9ae2a --- /dev/null +++ b/src/Events/appsettings.Production.json @@ -0,0 +1,10 @@ +{ + "globalSettings": { + "baseServiceUri": { + "vault": "https://vault.bitwarden.com", + "api": "https://api.bitwarden.com", + "identity": "https://identity.bitwarden.com", + "internalIdentity": "https://identity.bitwarden.com" + } + } +} diff --git a/src/Events/appsettings.Staging.json b/src/Events/appsettings.Staging.json new file mode 100644 index 0000000000..87ace9ae2a --- /dev/null +++ b/src/Events/appsettings.Staging.json @@ -0,0 +1,10 @@ +{ + "globalSettings": { + "baseServiceUri": { + "vault": "https://vault.bitwarden.com", + "api": "https://api.bitwarden.com", + "identity": "https://identity.bitwarden.com", + "internalIdentity": "https://identity.bitwarden.com" + } + } +} diff --git a/src/Events/appsettings.json b/src/Events/appsettings.json index 26bb0ac7ac..0d06d7dfe3 100644 --- a/src/Events/appsettings.json +++ b/src/Events/appsettings.json @@ -1,15 +1,25 @@ { - "Logging": { - "IncludeScopes": false, - "Debug": { - "LogLevel": { - "Default": "Warning" - } + "globalSettings": { + "selfHosted": false, + "projectName": "Events", + "baseServiceUri": { + "vault": "http://localhost:4001", + "api": "http://localhost:4000", + "identity": "http://localhost:33656", + "internalIdentity": "http://localhost:33656" }, - "Console": { - "LogLevel": { - "Default": "Warning" - } + "sqlServer": { + "connectionString": "SECRET" + }, + "identityServer": { + "certificateThumbprint": "SECRET" + }, + "storage": { + "connectionString": "SECRET" + }, + "documentDb": { + "uri": "SECRET", + "key": "SECRET" } } }