diff --git a/.idea/config/applicationhost.config b/.idea/config/applicationhost.config new file mode 100644 index 0000000..4ebad82 --- /dev/null +++ b/.idea/config/applicationhost.config @@ -0,0 +1,983 @@ + + + + + + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+ + +
+
+
+
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Core/Core.csproj b/Core/Core.csproj index 5a20b4d..5f9b7f3 100644 --- a/Core/Core.csproj +++ b/Core/Core.csproj @@ -16,6 +16,7 @@ + diff --git a/Core/MultiKeyEncryption/MasterKey.cs b/Core/MultiKeyEncryption/MasterKey.cs new file mode 100644 index 0000000..c2e40c1 --- /dev/null +++ b/Core/MultiKeyEncryption/MasterKey.cs @@ -0,0 +1,27 @@ +namespace Core.CryptoService +{ + internal class MasterKey + { + public async Task RotateMasterKey(int tenantId, string oldMasterKey, string newMasterKey) + { + // Hent alle bruger-keys for tenant + //var users = await GetTenantUsers(tenantId); + + //// Dekrypter connection string med gammel master key + //var connString = DecryptWithKey(encryptedConnString, oldMasterKey); + + //// Krypter med ny master key + //var newEncryptedConnString = EncryptWithKey(connString, newMasterKey); + + //// Re-krypter master key for alle brugere + //foreach (var user in users) + //{ + // var userKey = DeriveKeyFromPassword(user.Password); + // var newEncryptedMasterKey = EncryptWithKey(newMasterKey, userKey); + // await UpdateUserMasterKey(user.UserId, newEncryptedMasterKey); + //} + + //await UpdateTenantConnectionString(tenantId, newEncryptedConnString); + } + } +} diff --git a/Core/MultiKeyEncryption/SecureConnectionString.cs b/Core/MultiKeyEncryption/SecureConnectionString.cs new file mode 100644 index 0000000..d746e3c --- /dev/null +++ b/Core/MultiKeyEncryption/SecureConnectionString.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace Core.CryptoService +{ + public class SecureConnectionString + { + const string _masterKey = "5AFD74B1C26E87FE6656099E850DC67A"; + + public class EncryptedData + { + public string EncryptedConnectionString { get; set; } + public Dictionary UserMasterKeys { get; set; } = new(); + } + + public EncryptedData EncryptConnectionString(string connectionString) + { + var encryptedConnString = EncryptWithKey(connectionString, _masterKey); + var userKeys = new Dictionary(); + + + + return new EncryptedData + { + EncryptedConnectionString = encryptedConnString, + UserMasterKeys = userKeys + }; + } + + public string AddNewUser(string username, string password) + { + var userKey = DeriveKeyFromPassword(password); + var encryptedMasterKey = EncryptWithKey(_masterKey, userKey); + return encryptedMasterKey; + } + + public string Decrypt(string encryptedConnString, string encryptedMasterKey, string password) + { + var userKey = DeriveKeyFromPassword(password); + var masterKey = DecryptWithKey(encryptedMasterKey, userKey); + return DecryptWithKey(encryptedConnString, masterKey); + } + + private string DeriveKeyFromPassword(string password) + { + using var deriveBytes = new Rfc2898DeriveBytes( + password, + new byte[16], // Fast salt for simpelhed - i produktion bør dette være unikt per bruger + 10000, + HashAlgorithmName.SHA256); + + return Convert.ToBase64String(deriveBytes.GetBytes(32)); + } + + private string EncryptWithKey(string value, string key) + { + using var aes = Aes.Create(); + var keyBytes = Convert.FromBase64String(key); + aes.Key = keyBytes; + aes.GenerateIV(); + + using var encryptor = aes.CreateEncryptor(); + var valueBytes = Encoding.UTF8.GetBytes(value); + var encrypted = encryptor.TransformFinalBlock(valueBytes, 0, valueBytes.Length); + + var result = new byte[aes.IV.Length + encrypted.Length]; + Array.Copy(aes.IV, 0, result, 0, aes.IV.Length); + Array.Copy(encrypted, 0, result, aes.IV.Length, encrypted.Length); + + return Convert.ToBase64String(result); + } + + private string DecryptWithKey(string encryptedValue, string key) + { + var encryptedBytes = Convert.FromBase64String(encryptedValue); + using var aes = Aes.Create(); + + var keyBytes = Convert.FromBase64String(key); + aes.Key = keyBytes; + + var iv = new byte[16]; + Array.Copy(encryptedBytes, 0, iv, 0, iv.Length); + aes.IV = iv; + + using var decryptor = aes.CreateDecryptor(); + var decrypted = decryptor.TransformFinalBlock( + encryptedBytes, + iv.Length, + encryptedBytes.Length - iv.Length); + + return Encoding.UTF8.GetString(decrypted); + } + } +} diff --git a/Database/Core/DCL/SetupApplicationUser.cs b/Database/Core/DCL/SetupApplicationUser.cs index d90977b..f4236ff 100644 --- a/Database/Core/DCL/SetupApplicationUser.cs +++ b/Database/Core/DCL/SetupApplicationUser.cs @@ -25,11 +25,7 @@ namespace Database.Core.DCL { _db = db; } - - public void Setup(string schema = null) - { - throw new NotImplementedException(); - } + public void With(Command command) { _command = command; diff --git a/Database/Core/DCL/SetupDbAdmin.cs b/Database/Core/DCL/SetupDbAdmin.cs new file mode 100644 index 0000000..e929faa --- /dev/null +++ b/Database/Core/DCL/SetupDbAdmin.cs @@ -0,0 +1,119 @@ +using System.Data; +using Database.Common; +using Insight.Database; + +namespace Database.Core.DCL +{ + + /// + /// Only a superadmin or similar can create Application Users + /// + public class SetupDbAdmin : IDbConfigure + { + public class Command + { + public required string Schema { get; init; } + public required string User { get; init; } + public required string Password { get; init; } + } + + + IDbConnection _db; + Command _command; + + public SetupDbAdmin(IDbConnection db) + { + _db = db; + } + + + public void With(Command command) + { + _command = command; + + if (!Validations.IsValidSchemaName(_command.Schema)) + throw new ArgumentException("Invalid schema name", _command.Schema); + + using (var transaction = _db.OpenWithTransaction()) + { + try + { + CreateSchema(); + CreateRole(); + GrantSchemaRights(); + + transaction.Commit(); + } + catch (Exception ex) + { + transaction.Rollback(); + throw new InvalidOperationException("Failed to SetupApplicationUser in Database", ex); + } + } + + } + private void ExecuteSql(string sql) + { + _db.ExecuteSql(sql); + } + + private void CreateSchema() + { + var sql = $"CREATE SCHEMA IF NOT EXISTS {_command.Schema}"; + ExecuteSql(sql); + } + + private void CreateRole() + { + var sql = $@" + DO $$ + BEGIN + IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '{_command.User}') THEN + CREATE ROLE {_command.User} WITH CREATEDB CREATEROLE LOGIN PASSWORD '{_command.Password}'; + END IF; + END $$;"; + ExecuteSql(sql); + + var sql1 = $"ALTER ROLE {_command.User} SET search_path='{_command.Schema}';"; + ExecuteSql(sql1); + + var sql2 = $"ALTER SCHEMA {_command.Schema} OWNER TO {_command.User};"; + ExecuteSql(sql2); + + } + + private void GrantSchemaRights() + { + // Grant USAGE og alle CREATE rettigheder på schema niveau + //GRANT USAGE ON SCHEMA {_command.Schema} TO {_command.User}; + var sql = $@" + GRANT CREATE ON SCHEMA {_command.Schema} TO {_command.User};"; + + ExecuteSql(sql); + + // Grant rettigheder på eksisterende og fremtidige tabeller + //var sql1 = $"GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA {_command.Schema} TO {_command.User};"; + //ExecuteSql(sql1); + + //var sql2 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT ALL PRIVILEGES ON TABLES TO {_command.User};"; + //ExecuteSql(sql2); + + //// Grant sequence rettigheder + //var sql3 = $"GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA {_command.Schema} TO {_command.User};"; + //ExecuteSql(sql3); + + //// Grant execute på functions + //var sql4 = $"GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA {_command.Schema} TO {_command.User};"; + //ExecuteSql(sql4); + + //// Grant for fremtidige functions + //var sql5 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT EXECUTE ON FUNCTIONS TO {_command.User};"; + //ExecuteSql(sql5); + + //// Grant for fremtidige sequences + //var sql6 = $"ALTER DEFAULT PRIVILEGES IN SCHEMA {_command.Schema} GRANT USAGE ON SEQUENCES TO {_command.User};"; + //ExecuteSql(sql6); + } + + } +} diff --git a/Database/Core/DDL/SetupIdentitySystem.cs b/Database/Core/DDL/SetupIdentitySystem.cs index 2e39809..9ce0fba 100644 --- a/Database/Core/DDL/SetupIdentitySystem.cs +++ b/Database/Core/DDL/SetupIdentitySystem.cs @@ -3,63 +3,68 @@ using System.Data; namespace Database.Core.DDL { - /// - /// This is by purpose not async await - /// It is intended that this is created with the correct Application User, which is why the schema name is omitted. - /// - public class SetupIdentitySystem : IDbConfigure - { - public class Command { } + /// + /// This is by purpose not async await + /// It is intended that this is created with the correct Application User, which is why the schema name is omitted. + /// + public class SetupIdentitySystem : IDbConfigure + { + public class Command + { + public required string Schema { get; init; } + } - readonly IDbConnection _db; - IDbTransaction _transaction = null; - string _schema; + readonly IDbConnection _db; + IDbTransaction _transaction = null; + Command _command; - public SetupIdentitySystem(IDbConnection db) - { - _db = db; - } + public SetupIdentitySystem(IDbConnection db) + { + _db = db; + } - /// - /// Creates the system tables in the specified schema within a transaction. - /// - /// The schema name where the tables will be created. - public void With(Command emptyByIntention) - { - using (_transaction = _db.OpenWithTransaction()) - { - try - { - CreateUsersTable(); - CreateOrganizationsTable(); - CreateUserOrganizationsTable(); - SetupRLS(); + /// + /// Creates the system tables in the specified schema within a transaction. + /// + /// The schema name where the tables will be created. + public void With(Command command) + { + _command = command; - _transaction.Commit(); - } - catch (Exception ex) - { - _transaction.Rollback(); - throw new InvalidOperationException("Failed to SetupIdentitySystem. Transaction is rolled back", ex); - } - } - } - private void ExecuteSql(string sql) - { - if (string.IsNullOrEmpty(sql)) - throw new ArgumentNullException(nameof(sql)); + using (_transaction = _db.OpenWithTransaction()) + { + try + { + CreateUsersTable(); + CreateOrganizationsTable(); + CreateUserOrganizationsTable(); + SetupRLS(); - _db.ExecuteSql(sql); - } + _transaction.Commit(); + } + catch (Exception ex) + { + _transaction.Rollback(); + throw new InvalidOperationException("Failed to SetupIdentitySystem. Transaction is rolled back", ex); + } + } + } + private void ExecuteSql(string sql) + { + if (string.IsNullOrEmpty(sql)) + throw new ArgumentNullException(nameof(sql)); + + _db.ExecuteSql(sql); + } - /// - /// Creates the users table - /// - void CreateUsersTable() - { - var sql = @" - CREATE TABLE IF NOT EXISTS users ( + /// + /// Creates the users table + /// + void CreateUsersTable() + { + var sql = @$" + CREATE TABLE IF NOT EXISTS {_command.Schema}.users ( id SERIAL PRIMARY KEY, email VARCHAR(256) NOT NULL UNIQUE, password_hash VARCHAR(256) NOT NULL, @@ -73,73 +78,73 @@ namespace Database.Core.DDL last_login_at TIMESTAMPTZ NULL );"; - ExecuteSql(sql); + ExecuteSql(sql); - } + } - /// - /// Creates the organizations table - /// - void CreateOrganizationsTable() - { - var sql = @" - CREATE TABLE IF NOT EXISTS organizations ( + /// + /// Creates the organizations table + /// + void CreateOrganizationsTable() + { + var sql = @$" + CREATE TABLE IF NOT EXISTS {_command.Schema}.organizations ( id SERIAL PRIMARY KEY, connection_string VARCHAR(500) NOT NULL, is_active BOOLEAN NOT NULL DEFAULT TRUE, - created_by INTEGER NOT NULL REFERENCES users(id), + created_by INTEGER NOT NULL REFERENCES {_command.Schema}.users(id), created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP );"; - ExecuteSql(sql); + ExecuteSql(sql); - } + } - /// - /// Creates the user_organizations table - /// - void CreateUserOrganizationsTable() - { - var sql = @" - CREATE TABLE IF NOT EXISTS user_organizations ( - user_id INTEGER NOT NULL REFERENCES users(id), - organization_id INTEGER NOT NULL REFERENCES organizations(id), + /// + /// Creates the user_organizations table + /// + void CreateUserOrganizationsTable() + { + var sql = @$" + CREATE TABLE IF NOT EXISTS {_command.Schema}.user_organizations ( + user_id INTEGER NOT NULL REFERENCES {_command.Schema}.users(id), + organization_id INTEGER NOT NULL REFERENCES {_command.Schema}.organizations(id), pin_code VARCHAR(10) NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id, organization_id) );"; - ExecuteSql(sql); + ExecuteSql(sql); - } + } - /// - /// Sets up Row Level Security (RLS) for the organizations and user_organizations tables. - /// - void SetupRLS() - { - var sql = new[] - { - "ALTER TABLE organizations ENABLE ROW LEVEL SECURITY;", - "ALTER TABLE user_organizations ENABLE ROW LEVEL SECURITY;", - "DROP POLICY IF EXISTS organization_access ON organizations;", - @"CREATE POLICY organization_access ON organizations + /// + /// Sets up Row Level Security (RLS) for the organizations and user_organizations tables. + /// + void SetupRLS() + { + var sql = new[] + { + $"ALTER TABLE {_command.Schema}.organizations ENABLE ROW LEVEL SECURITY;", + $"ALTER TABLE {_command.Schema}.user_organizations ENABLE ROW LEVEL SECURITY;", + $"DROP POLICY IF EXISTS organization_access ON {_command.Schema}.organizations;", + @$"CREATE POLICY organization_access ON {_command.Schema}.organizations USING (id IN ( SELECT organization_id - FROM user_organizations + FROM {_command.Schema}.user_organizations WHERE user_id = current_setting('app.user_id', TRUE)::INTEGER - ));", - "DROP POLICY IF EXISTS user_organization_access ON user_organizations;", - @"CREATE POLICY user_organization_access ON user_organizations - USING (user_id = current_setting('app.user_id', TRUE)::INTEGER);" - }; + )) WITH CHECK (true);", + $"DROP POLICY IF EXISTS user_organization_access ON {_command.Schema}.user_organizations;", + @$"CREATE POLICY user_organization_access ON {_command.Schema}.user_organizations + USING (user_id = current_setting('app.user_id', TRUE)::INTEGER) WITH CHECK (true);" + }; - foreach (var statement in sql) - { - ExecuteSql(statement); - } - } + foreach (var statement in sql) + { + ExecuteSql(statement); + } + } - } + } } \ No newline at end of file diff --git a/SetupInfrastructure/Program.cs b/SetupInfrastructure/Program.cs index af340fd..068aa9f 100644 --- a/SetupInfrastructure/Program.cs +++ b/SetupInfrastructure/Program.cs @@ -48,42 +48,49 @@ namespace SetupInfrastructure { Console.ForegroundColor = ConsoleColor.Green; var sw = new Stopwatch(); - Console.Write("Database.Core.DCL.SetupApplicationUser..."); - sw.Start(); - var setupApplicationUser = _container.Resolve(); - setupApplicationUser.With(new Database.Core.DCL.SetupApplicationUser.Command { Password = "3911", Schema = "system", User = "sathumper" }); - Console.WriteLine($"DONE, took: {sw.ElapsedMilliseconds} ms"); + + Console.Write("Database.Core.DCL.SetupDbAdmin..."); + sw.Start(); + var setupDbAdmin = _container.Resolve(); + setupDbAdmin.With(new Database.Core.DCL.SetupDbAdmin.Command { Password = "3911", Schema = "system", User = "heimdall" }); + Console.WriteLine($"DONE, took: {sw.ElapsedMilliseconds} ms"); + Console.WriteLine("::"); Console.WriteLine("::"); - Console.Write("Database.Core.DDL.SetupIdentitySystem..."); sw.Restart(); + //create new container with application user, we use that role from now. - _container = new Startup().ConfigureContainer(new Startup.ConnectionStringTemplateParameters("sathumper", "3911")); + _container = new Startup().ConfigureContainer(new Startup.ConnectionStringTemplateParameters("heimdall", "3911")); var setupIdentitySystem = _container.Resolve(); - setupIdentitySystem.With(new Database.Core.DDL.SetupIdentitySystem.Command()); + setupIdentitySystem.With(new Database.Core.DDL.SetupIdentitySystem.Command { Schema = "system"}); Console.WriteLine($"DONE, took: {sw.ElapsedMilliseconds} ms"); Console.WriteLine("::"); Console.WriteLine("::"); - Console.Write("Database.ConfigurationManagementSystem.SetupConfiguration..."); sw.Restart(); var setupConfigurationSystem = _container.Resolve(); setupConfigurationSystem.With(new Database.ConfigurationManagementSystem.SetupConfiguration.Command()); Console.Write($"DONE, took: {sw.ElapsedMilliseconds} ms"); - // SetupConfiguration + + Console.WriteLine("::"); + Console.WriteLine("::"); + Console.Write("Database.Core.DCL.SetupApplicationUser..."); + sw.Start(); + var setupApplicationUser = _container.Resolve(); + setupApplicationUser.With(new Database.Core.DCL.SetupApplicationUser.Command { Password = "3911", Schema = "system", User = "sathumper" }); + Console.WriteLine($"DONE, took: {sw.ElapsedMilliseconds} ms"); + //and a lot of other tables that we haven't defined yet - //and a lot of other tables that we haven't defined yet + // input configurations!!! TODO:Missing - // input configurations!!! TODO:Missing - - Console.ForegroundColor = _foregroundColor; + Console.ForegroundColor = _foregroundColor; } diff --git a/SqlManagement/.dbeaver/.project-metadata.json.bak b/SqlManagement/.dbeaver/.project-metadata.json.bak index 91b0730..5119abe 100644 --- a/SqlManagement/.dbeaver/.project-metadata.json.bak +++ b/SqlManagement/.dbeaver/.project-metadata.json.bak @@ -1 +1 @@ -{"resources":{"Scripts/SmartConfigSystem.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"},"Scripts/grant-privileges.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"}}} \ No newline at end of file +{"resources":{"Scripts/Script-1.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"},"Scripts/Script.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44"},"Scripts/SmartConfigSystem.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"},"Scripts/grant-privileges.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"}}} \ No newline at end of file diff --git a/SqlManagement/.dbeaver/project-metadata.json b/SqlManagement/.dbeaver/project-metadata.json index f792e7c..3200961 100644 --- a/SqlManagement/.dbeaver/project-metadata.json +++ b/SqlManagement/.dbeaver/project-metadata.json @@ -1 +1 @@ -{"resources":{"Scripts/Script-1.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"},"Scripts/Script.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain","default-schema":"system"},"Scripts/SmartConfigSystem.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01","default-schema":"public"},"Scripts/grant-privileges.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"}}} \ No newline at end of file +{"resources":{"Scripts/Script-1.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"},"Scripts/Script.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"},"Scripts/SmartConfigSystem.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptdb01"},"Scripts/grant-privileges.sql":{"default-datasource":"postgres-jdbc-1948450a8b4-5fc9eec404e65c44","default-catalog":"ptmain"}}} \ No newline at end of file diff --git a/SqlManagement/Scripts/Script.sql b/SqlManagement/Scripts/Script.sql index e69de29..68ca72d 100644 --- a/SqlManagement/Scripts/Script.sql +++ b/SqlManagement/Scripts/Script.sql @@ -0,0 +1,40 @@ + +GRANT USAGE ON SCHEMA "system" TO heimdall; +GRANT CREATE ON SCHEMA "system" TO heimdall + +create schema "system" + + ALTER DEFAULT PRIVILEGES FOR ROLE heimdall IN SCHEMA "system" +GRANT ALL PRIVILEGES ON TABLES TO heimdall; + +-- Og for eksisterende tabeller +GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA "system" TO heimdall; + + ALTER TABLE susers OWNER TO db_admin; + GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA your_schema TO sathumper; + + + CREATE ROLE heimdall WITH LOGIN PASSWORD '3911'; +COMMENT ON ROLE heimdall IS 'Security auditor and guardian'; +drop role heimdall + + +set role 'heimdall' +ALTER ROLE heimdall SET search_path = "system" +drop table system.foo + +SELECT CURRENT_ROLE; +SELECT rolname FROM pg_roles +select system_user() + +SET ROLE heimdall; +RESET ALL; -- Nulstil alle sessionsvariabler til deres standardværdier +SHOW search_path; -- Burde nu vise den konfigurerede værdi + +SHOW search_path; + +create table system.foos(id int) + +select * from system.foo + + diff --git a/SqlManagement/Scripts/grant-privileges.sql b/SqlManagement/Scripts/grant-privileges.sql index ec169fd..78bbc4d 100644 --- a/SqlManagement/Scripts/grant-privileges.sql +++ b/SqlManagement/Scripts/grant-privileges.sql @@ -19,9 +19,6 @@ WHERE useconfig IS NOT NULL ALTER ROLE sathumper1 SET search_path='ss32' - - CREATE USER fm WITH PASSWORD 'asd' - await _db.ExecuteAsync(sql); \ No newline at end of file diff --git a/Tests/PasswordHasherTest.cs b/Tests/PasswordHasherTest.cs index a635ac2..512e706 100644 --- a/Tests/PasswordHasherTest.cs +++ b/Tests/PasswordHasherTest.cs @@ -5,12 +5,35 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Extensions.Logging; using Core.Telemetry; using Core.Entities.Users; +using System.Diagnostics; +using Sodium; namespace Tests { [TestClass] public class PasswordHasherTests : TestFixture { + + [TestMethod] + public void MyTestMethod() + { + var stopwatch = Stopwatch.StartNew(); + + byte[] salt = PasswordHash.ScryptGenerateSalt(); + + // 2. Konverter password til byte[] + byte[] passwordBytes = System.Text.Encoding.UTF8.GetBytes("password123"); + + // 3. Kald ScryptHashBinary korrekt + byte[] hash = PasswordHash.ScryptHashBinary( + password: passwordBytes, + salt: salt, // 32-byte array + limit: PasswordHash.Strength.Interactive, + outputLength: 32 + ); + + stopwatch.Stop(); + } [TestMethod] public void HashPassword_ShouldCreateValidHashFormat() { @@ -23,7 +46,7 @@ namespace Tests // Assert Assert.AreEqual(3, parts.Length); - Assert.AreEqual("100000", parts[0]); + Assert.AreEqual("600000", parts[0]); } [TestMethod] diff --git a/Tests/PostgresTests.cs b/Tests/PostgresTests.cs index 61be7c2..956f2af 100644 --- a/Tests/PostgresTests.cs +++ b/Tests/PostgresTests.cs @@ -39,10 +39,12 @@ namespace Tests ); } var logger = Container.Resolve(); - + + for (int i = 0; i < 5; i++) { - logger.TrackTrace("Hello 23" , Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Information); + + logger.TrackTrace("Hello 23", Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Information); } diff --git a/Tests/SecureConnectionStringTests.cs b/Tests/SecureConnectionStringTests.cs new file mode 100644 index 0000000..40d1549 --- /dev/null +++ b/Tests/SecureConnectionStringTests.cs @@ -0,0 +1,11 @@ +using Autofac; +using System.Data; +using Insight.Database; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.Extensions.Logging; +using Core.Telemetry; + +namespace Tests +{ + +} \ No newline at end of file diff --git a/Tests/TestFixture.cs b/Tests/TestFixture.cs index 0c9cf5a..fdb8df0 100644 --- a/Tests/TestFixture.cs +++ b/Tests/TestFixture.cs @@ -26,19 +26,12 @@ namespace Tests return configuration; } - /// - /// Should not be overriden. Rather override PreArrangeAll to setup data needed for a test class. - /// Override PrebuildContainer with a method that does nothing to prevent early build of IOC container - /// - [TestInitialize] - public void Setup() + protected TestFixture() { CreateContainerBuilder(); Container = ContainerBuilder.Build(); - } - protected virtual void CreateContainerBuilder() { IConfigurationRoot configuration = Configuration();