Generating a certificate for IS

This commit is contained in:
Zoe Roux 2020-04-05 20:12:00 +02:00
parent e1286eda28
commit 539733f637
6 changed files with 119 additions and 58 deletions

View File

@ -0,0 +1,114 @@
using System;
using System.IO;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using IdentityServer4.Extensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Configuration;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.X509;
using X509Certificate = Org.BouncyCastle.X509.X509Certificate;
namespace Kyoo.Controllers
{
public class AuthManager
{
public const string CertificateFile = "certificate.pfx";
public static X509Certificate2 GetSiginCredential(IConfiguration configuration)
{
if (File.Exists(CertificateFile))
{
return new X509Certificate2(CertificateFile, configuration.GetValue<string>("certificatePassword"),
X509KeyStorageFlags.MachineKeySet |
X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable
);
}
SecureRandom random = new SecureRandom();
X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
certificateGenerator.SetSerialNumber(BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random));
certificateGenerator.SetIssuerDN(new X509Name($"C=NL, O=SDG, CN=Kyoo"));
certificateGenerator.SetSubjectDN(new X509Name($"C=NL, O=SDG, CN=Kyoo"));
certificateGenerator.SetNotBefore(DateTime.UtcNow.Date);
certificateGenerator.SetNotAfter(DateTime.UtcNow.Date.AddYears(1));
KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, 2048);
RsaKeyPairGenerator keyPairGenerator = new RsaKeyPairGenerator();
keyPairGenerator.Init(keyGenerationParameters);
AsymmetricCipherKeyPair subjectKeyPair = keyPairGenerator.GenerateKeyPair();
certificateGenerator.SetPublicKey(subjectKeyPair.Public);
AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair;
const string signatureAlgorithm = "SHA256WithRSA";
Asn1SignatureFactory signatureFactory = new Asn1SignatureFactory(signatureAlgorithm,issuerKeyPair.Private);
X509Certificate bouncyCert = certificateGenerator.Generate(signatureFactory);
X509Certificate2 certificate;
Pkcs12Store store = new Pkcs12StoreBuilder().Build();
store.SetKeyEntry("Kyoo_key", new AsymmetricKeyEntry(subjectKeyPair.Private), new [] {new X509CertificateEntry(bouncyCert)});
string pass = configuration.GetValue<string>("certificatePassword"); //Guid.NewGuid().ToString("x");
using (MemoryStream pfxStream = new MemoryStream())
{
store.Save(pfxStream, pass.ToCharArray(), random);
certificate = new X509Certificate2(pfxStream.ToArray(), pass, X509KeyStorageFlags.Exportable);
using (FileStream fileStream = File.OpenWrite(CertificateFile))
pfxStream.WriteTo(fileStream);
}
return certificate;
}
}
public class AuthorizationValidatorHandler : AuthorizationHandler<AuthorizationValidator>
{
private readonly IConfiguration _configuration;
public AuthorizationValidatorHandler(IConfiguration configuration)
{
_configuration = configuration;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AuthorizationValidator requirement)
{
if (!context.User.IsAuthenticated())
{
string defaultPerms = _configuration.GetValue<string>("defaultPermissions");
if (defaultPerms.Split(',').Contains(requirement.Permission.ToLower()))
context.Succeed(requirement);
}
else
{
Claim perms = context.User.Claims.FirstOrDefault(x => x.Type == "permissions");
if (perms != null && perms.Value.Split(",").Contains(requirement.Permission.ToLower()))
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
public class AuthorizationValidator : IAuthorizationRequirement
{
public string Permission;
public AuthorizationValidator(string permission)
{
Permission = permission;
}
}
}

View File

@ -1,47 +0,0 @@
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using IdentityServer4.Extensions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Configuration;
namespace Kyoo.Controllers
{
public class AuthorizationValidatorHandler : AuthorizationHandler<AuthorizationValidator>
{
private readonly IConfiguration _configuration;
public AuthorizationValidatorHandler(IConfiguration configuration)
{
_configuration = configuration;
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, AuthorizationValidator requirement)
{
if (!context.User.IsAuthenticated())
{
string defaultPerms = _configuration.GetValue<string>("defaultPermissions");
if (defaultPerms.Split(',').Contains(requirement.Permission.ToLower()))
context.Succeed(requirement);
}
else
{
Claim perms = context.User.Claims.FirstOrDefault(x => x.Type == "permissions");
if (perms != null && perms.Value.Split(",").Contains(requirement.Permission.ToLower()))
context.Succeed(requirement);
}
return Task.CompletedTask;
}
}
public class AuthorizationValidator : IAuthorizationRequirement
{
public string Permission;
public AuthorizationValidator(string permission)
{
Permission = permission;
}
}
}

View File

@ -18,6 +18,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Portable.BouncyCastle" Version="1.8.6.7" />
<ProjectReference Include="../Kyoo.Common/Kyoo.Common.csproj" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />

View File

@ -61,7 +61,6 @@ namespace Kyoo
options.UserInteraction.LogoutUrl = publicUrl + "logout";
})
.AddAspNetIdentity<User>()
.AddSigningCredentials()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
@ -78,7 +77,7 @@ namespace Kyoo
.AddInMemoryIdentityResources(IdentityContext.GetIdentityResources())
.AddInMemoryApiResources(IdentityContext.GetApis())
.AddProfileService<AccountController>()
.AddDeveloperSigningCredential(); // TODO remove the developer signin
.AddSigningCredential(AuthManager.GetSiginCredential(Configuration));
services.AddAuthentication()
.AddJwtBearer(options =>

View File

@ -10,22 +10,17 @@
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"Database": "Data Source=kyoo.db"
},
"IdentityServer": {
"Key": {
"Type": "Development"
}
},
"certificatePassword": "passphrase",
"transmuxTempPath": "cached/kyoo/transmux",
"transcodeTempPath": "cached/kyoo/transcode",
"peoplePath": "people",
"profilePicturePath": "users/",
"plugins": "plugins/",
"defaultPermissions": "read,play",
"defaultPermissions": "",
"regex": "(\\/(?<Collection>.*)\\/)?.*\\/(?<ShowTitle>.+?)(( S(?<Season>\\d+)E(?<Episode>\\d+)| (?<Absolute>\\d+)))?\\.",
}

View File

@ -1 +0,0 @@
{"KeyId":"mkaygTF8pb-42wV_HvSUCQ","Parameters":{"D":"usyImLSKe8Gvh65XyygNoe9bCffxcB9maRAAL9tXou89QHc4WhPvCjRDlryOwNUxNWJvduDXJm+AenWbSx7/PNVzaKaK6j/GKt9OMsD//9ubEswP9zhNFn9zAzmWsp2wSMEM+1fU6VcXc9MCwjySP3DtHiw3ZwFUvfP4pm3PhKwaI3TKe2rmB9mwziiv9SSd+bwbKlVlGmMM4UVMwD/VYmJZZMB8NaQY2PmdJHztyp4NYJIMFnGFaJVN9GSFC1qv2btKhlZrL7InGdATbzUC82+Ff0st5YX4omJyb8DJ25SiCSXzKkeLWafcCedYdJwIPSxAgd9edCQLUNvORa26qQ==","DP":"0x2WZoveXkd9cYs4xGpL3cKmg5RQe1IBNy19tqLhpiCOqtzgz7agCbEBSsHsPQVclrQMp+GvBbuWTKEAj4DR/N2o+ir6V0W80VN8/2K4PX7wo9ryJAmUXNp4b231ubJv4neDGqF2j0g+WWxt5Gh6gx+FJjkGENYs5VJ7kFSc+fs=","DQ":"HQr0bM//+68PwegI6PSmFYgNMciMsnXGpn9xElU2Ed8EiF8dRW3LBjl8y3tsuZVwHbteZtlZJqUtd0kuwkC+5Kts1dEds8FOXfrZgpt/n+APOr14707yaxrcWhGkJu9kCjRsAbhsxtScxQE/sUb+5naTF5ypmORplL3O6ZnJ8L0=","Exponent":"AQAB","InverseQ":"IYckPpRj0eq7UF3YrzSt7sLPYdz/S1nfBJl4gNKEYvnwysaxg2iOq2u/4hu7+r1Jf8+j6e1dcOJqN4jPXyq2ycQ0X5BLNHENXBjvRrfaUD35bBMz2vKRq423sXPAV2k1Mpt6StZSAjyxF741IIQ+X1W5IVuuO9awK9ruw9bpR2I=","Modulus":"yoIp2j1kI5sku7k16xJNLEt7uw4LQY+UX3onsgdf69aNNXk2j6IyoW6dE9lAGRYKsNkKSH2kvUBTHCX78j0Mg0dInNyB1s7MgS5t8ypc4y5lIE+xFEXKAKeH6lZ9NC+PNwtCSY9iNAteiPO1ittmzkS7QR9fgHQ/8NwYuU3AxQUxf5QULuYWIE4rKryQHqlQzqvg7cZizcuINXxG3oUiSGWg1aYQUcjY07wWJFvVwsV7pjKTSL0edDCoqg8bQ/F97aDuP4e0QKaALs1GkXb854Kp977EitxLOAYkJrq4X/OkTZjwXjQhXnDwiwacuCnqLpDz4OX1Nr7EKJz1ZzmGrw==","P":"7zjThXlm/qG07URGqKTnq1QWGwoCCxXfVK5u0xbzhuPtjISAk2ijs4Bp7XNbQD63zdO52k7F8od8s4HXBjCG5rzpMNxpMef3SPfBX2f726XtQQYhXEW90iXeIUl55Hp41M+CO9GQs4XOy+k/AtkDbbaR7EKAQP7w4ddhRSJUyqM=","Q":"2LYnkzwnZdd4Femjg/6whVLFJZ8g78dew/0SnlX++3ShOX9GheACcunKVs6LD8X9ALay2ondx+4qRuep0wphc4UK6HoN9S/GnhJZDt2GjfAPPPegEfOEW+jIcX/COYX1unfcCVb17Cl+dWfQRa6RXtvfputA1u6N+wb0wtcmwIU="}}