diff --git a/sechub-doc/src/docs/asciidoc/diagrams/diagram_encryption_sechub_config.puml b/sechub-doc/src/docs/asciidoc/diagrams/diagram_encryption_sechub_config.puml index c945ecadef..d0d75ba24a 100644 --- a/sechub-doc/src/docs/asciidoc/diagrams/diagram_encryption_sechub_config.puml +++ b/sechub-doc/src/docs/asciidoc/diagrams/diagram_encryption_sechub_config.puml @@ -8,26 +8,23 @@ hide empty methods 'You can find more examles at https://plantuml.com/class-diagram 'skinparam linetype ortho -skinparam linetype polyline +'skinparam linetype polyline -database DB { - -} - -database EventBus{ +database START_ENCRYPTION_ROTATION as rotateEvent #darkorange { } - -package com.mercedesbenz.sechub.commons.encryption as common_encrypt { - - class PersistentCipherFactory - class PersistentCipher - class EncryptionSupport +note right of rotateEvent +asynchronous +end note +database SCHEDULE_ENCRYPTION_POOL_INITIALIZED as poolInitEvent #limegreen { } +note right of poolInitEvent +asynchronous +end note package com.mercedesbenz.sechub.domain.administration { package encryption as adm_encryption{ class EncryptionAdministrationRestController - class EncryptionRotationService #darkorange + class AdministrationEncryptionRotationService } } @@ -46,98 +43,54 @@ package com.mercedesbenz.sechub.domain.schedule{ resolveUnencryptedConfiguration(ScheduleSecHubJob job) } - class SecHubJobRepository + class ScheduleSecHubJobEncryptionUpdateService #limegreen ##green { + updateEncryptedDataIfNecessary() + } } package encryption as schedule_encryption { - class ScheduleSecHubJobEncryptionUpdateService #dodgerblue { - updateEncryptionData(int blockSizeToUpdate) - } - - class ScheduleRefreshEncryptionServiceSetupTriggerService #mediumpurple { + class ScheduleRefreshEncryptionServiceSetupTriggerService #aliceblue ##darkblue { triggerEncryptionSetupRefresh() } - class ScheduleEncryptionService { + class ScheduleEncryptionService #aliceblue ##darkblue{ applicationStarted() refreshEncryptionPoolAndLatestIdIfNecessary() - encryptWithLatestCipher() + + encryptWithLatestCipher(String plainText) String decryptToString(byte[] encrypted, Long encryptionPoolId, InitializationVector initialVector) ScheduleEncryptionResult rotateEncryption(byte[] data, Long oldCipherPoolId, InitializationVector oldInitialVector) } - class ScheduleCipherPoolData { - } - - class ScheduleCipherPoolDataRepository { - + class ScheduleCipherPoolData #darkorange { } - class ScheduleEncryptionPool #mediumpurple { + class ScheduleEncryptionPool #aliceblue ##darkblue { PersistentCipher getCipherForPoolId(Long poolId) } - class ScheduleEncryptionPoolFactory #mediumpurple { - + class ScheduleEncryptionRotationService #darkorange { + startEncryptionRotation() } - - class ScheduleLatestCipherPoolIdResolver - - class ScheduleEncryptionRotationService #darkorange - - - note top of ScheduleRefreshEncryptionServiceSetupTriggerService - To use new encryption on all server cluster - member after same time. - end note + } +EncryptionAdministrationRestController -> AdministrationEncryptionRotationService +AdministrationEncryptionRotationService --> rotateEvent +rotateEvent -[#darkorange]-> ScheduleEncryptionRotationService - - -ScheduleRefreshEncryptionServiceSetupTriggerService --> ScheduleEncryptionService - -ScheduleEncryptionService -> ScheduleLatestCipherPoolIdResolver: uses -ScheduleEncryptionService o-- ScheduleEncryptionPool - -ScheduleEncryptionService -> EncryptionSupport: uses -ScheduleEncryptionService -> ScheduleEncryptionPoolFactory: uses - -ScheduleEncryptionPoolFactory --> ScheduleEncryptionPool : creates -PersistentCipherFactory -> PersistentCipher: creates -ScheduleEncryptionPoolFactory -> PersistentCipherFactory: uses -ScheduleLatestCipherPoolIdResolver -> ScheduleCipherPoolDataRepository -ScheduleEncryptionPoolFactory -- ScheduleCipherPoolDataRepository: uses -ScheduleEncryptionPoolFactory -- ScheduleCipherPoolData - -ScheduleEncryptionPool -- PersistentCipher - -ScheduleCipherPoolData --> DB -ScheduleSecHubJob --> DB -ScheduleCipherPoolDataRepository --> ScheduleCipherPoolData - -SecHubConfigurationModelAccess -> ScheduleEncryptionService : uses - - -SecHubConfigurationModelAccess -> ScheduleSecHubJob - -SecHubJobFactory -> ScheduleSecHubJob: creates -SecHubJobFactory -> ScheduleEncryptionService : uses - - -ScheduleSecHubJobEncryptionUpdateService -> ScheduleEncryptionService - - -ScheduleSecHubJobEncryptionUpdateService --> SecHubJobRepository -SecHubJobRepository --> ScheduleSecHubJob - - -EncryptionAdministrationRestController --> EncryptionRotationService -EncryptionRotationService --> EventBus -EventBus --> ScheduleEncryptionRotationService - -ScheduleEncryptionRotationService --> ScheduleCipherPoolData : creates -'ScheduleEncryptionRotationService --> ScheduleCipherPoolDataRepository +ScheduleEncryptionRotationService -[#darkorange]-> ScheduleCipherPoolData : (A1) create new + +ScheduleRefreshEncryptionServiceSetupTriggerService -[#darkblue]-> ScheduleEncryptionService: (B1) trigger refresh +ScheduleEncryptionRotationService -[#darkorange]-> ScheduleEncryptionService: (A2) trigger refresh +ScheduleEncryptionPool <-[#darkblue]- ScheduleEncryptionService: (A3,B2): refesh pool + +ScheduleEncryptionService -[#darkblue]-> poolInitEvent: (A4,B3): trigger update +poolInitEvent -[#limegreen]-> ScheduleSecHubJobEncryptionUpdateService: (A5,B4): trigger update + +SecHubConfigurationModelAccess --> ScheduleSecHubJob +SecHubJobFactory ..> ScheduleSecHubJob: create +ScheduleSecHubJobEncryptionUpdateService -[#limegreen]-> ScheduleSecHubJob: updates @enduml diff --git a/sechub-doc/src/docs/asciidoc/diagrams/diagram_encryption_sechub_config2.puml b/sechub-doc/src/docs/asciidoc/diagrams/diagram_encryption_sechub_config2.puml deleted file mode 100644 index b99051b8ea..0000000000 --- a/sechub-doc/src/docs/asciidoc/diagrams/diagram_encryption_sechub_config2.puml +++ /dev/null @@ -1,144 +0,0 @@ -' SPDX-License-Identifier: MIT -@startuml - -'Hide empty parts: -hide empty fields -hide empty methods - -'You can find more examles at https://plantuml.com/class-diagram - -'skinparam linetype ortho -skinparam linetype polyline - -database DB { - -} - -database EventBus{ -} - -package com.mercedesbenz.sechub.commons.encryption as common_encrypt { - - class PersistentCipherFactory - class PersistentCipher - class EncryptionSupport -} - -package com.mercedesbenz.sechub.domain.administration { - package encryption as adm_encryption{ - class EncryptionAdministrationRestController - class EncryptionRotationService #darkorange - } -} - -package com.mercedesbenz.sechub.domain.schedule{ - - package job as schedule_job { - class ScheduleSecHubJob { - byte[] getEncryptedConfiguration() - } - - class SecHubJobFactory { - - } - - class ScheduleSecHubJobEncryptionUpdateService #dodgerblue { - updateEncryptionData(int blockSizeToUpdate) - } - - class SecHubConfigurationModelAccess { - resolveUnencryptedConfiguration(ScheduleSecHubJob job) - } - - class SecHubJobRepository - - } - - package encryption as schedule_encryption { - - class ScheduleRefreshEncryptionServiceSetupTriggerService #mediumpurple { - triggerEncryptionSetupRefresh() - } - - class ScheduleRotateDataEncryptionTriggerService #dodgerblue { - triggerUpdateOfEncryptedData() - } - - class ScheduleEncryptionService { - applicationStarted() - refreshEncryptionPoolAndLatestIdIfNecessary() - encryptWithLatestCipher() - String decryptToString(byte[] encrypted, Long encryptionPoolId, InitializationVector initialVector) - ScheduleEncryptionResult rotateEncryption(byte[] data, Long oldCipherPoolId, InitializationVector oldInitialVector) - } - - class ScheduleCipherPoolData { - } - - class ScheduleCipherPoolDataRepository { - - } - - class ScheduleEncryptionPool #mediumpurple { - PersistentCipher getCipherForPoolId(Long poolId) - } - - class ScheduleEncryptionPoolFactory #mediumpurple { - - } - - class ScheduleLatestCipherPoolIdResolver - - class ScheduleEncryptionRotationService #darkorange - - - } - -} - - -ScheduleRefreshEncryptionServiceSetupTriggerService --> ScheduleEncryptionService - -ScheduleEncryptionService -> ScheduleLatestCipherPoolIdResolver: uses -ScheduleEncryptionService o-- ScheduleEncryptionPool - -ScheduleEncryptionService -> EncryptionSupport: uses -ScheduleEncryptionService -> ScheduleEncryptionPoolFactory: uses - -ScheduleEncryptionPoolFactory --> ScheduleEncryptionPool : creates -PersistentCipherFactory -> PersistentCipher: creates -ScheduleEncryptionPoolFactory -> PersistentCipherFactory: uses -ScheduleLatestCipherPoolIdResolver -> ScheduleCipherPoolDataRepository -ScheduleEncryptionPoolFactory -- ScheduleCipherPoolDataRepository: uses -ScheduleEncryptionPoolFactory -- ScheduleCipherPoolData - -ScheduleEncryptionPool -- PersistentCipher - -ScheduleCipherPoolData --> DB -ScheduleSecHubJob --> DB -ScheduleCipherPoolDataRepository --> ScheduleCipherPoolData - -SecHubConfigurationModelAccess -> ScheduleEncryptionService : uses - - -SecHubConfigurationModelAccess -> ScheduleSecHubJob - -SecHubJobFactory -> ScheduleSecHubJob: creates -SecHubJobFactory -> ScheduleEncryptionService : uses - -ScheduleRotateDataEncryptionTriggerService -> ScheduleSecHubJobEncryptionUpdateService: calls -ScheduleSecHubJobEncryptionUpdateService -> ScheduleEncryptionService - - -ScheduleSecHubJobEncryptionUpdateService --> SecHubJobRepository -SecHubJobRepository --> ScheduleSecHubJob - - -EncryptionAdministrationRestController --> EncryptionRotationService -EncryptionRotationService --> EventBus -EventBus --> ScheduleEncryptionRotationService - -ScheduleEncryptionRotationService --> ScheduleCipherPoolData : creates -'ScheduleEncryptionRotationService --> ScheduleCipherPoolDataRepository - -@enduml diff --git a/sechub-doc/src/docs/asciidoc/documents/architecture/08_concepts.adoc b/sechub-doc/src/docs/asciidoc/documents/architecture/08_concepts.adoc index 75accaf4ff..ee26c07351 100644 --- a/sechub-doc/src/docs/asciidoc/documents/architecture/08_concepts.adoc +++ b/sechub-doc/src/docs/asciidoc/documents/architecture/08_concepts.adoc @@ -44,6 +44,6 @@ include::../shared/concepts/concept_analytic.adoc[] include::../shared/concepts/concept_statistic.adoc[] === Data encryption -include::../shared/concepts/concept_data_encryption.adoc[] +include::../shared/concepts/concept_sechub_data_encryption.adoc[] diff --git a/sechub-doc/src/docs/asciidoc/documents/shared/concepts/concept_auto_clean.adoc b/sechub-doc/src/docs/asciidoc/documents/shared/concepts/concept_auto_clean.adoc index 4613ec8959..ebab254553 100644 --- a/sechub-doc/src/docs/asciidoc/documents/shared/concepts/concept_auto_clean.adoc +++ b/sechub-doc/src/docs/asciidoc/documents/shared/concepts/concept_auto_clean.adoc @@ -3,6 +3,8 @@ === Auto cleanup To prevent full hard drives there is an option to automatically remove old data. +It also cleans up old encryption settings when it comes to <>. + [NOTE] ==== See also diff --git a/sechub-doc/src/docs/asciidoc/documents/shared/concepts/concept_data_encryption.adoc b/sechub-doc/src/docs/asciidoc/documents/shared/concepts/concept_data_encryption.adoc deleted file mode 100644 index eee671e4c2..0000000000 --- a/sechub-doc/src/docs/asciidoc/documents/shared/concepts/concept_data_encryption.adoc +++ /dev/null @@ -1,273 +0,0 @@ -// SPDX-License-Identifier: MIT -[[section-shared-concepts-data-encryption]] -In SecHub we have some sensitive data we want to be encrypted. For example: Inside remote data -section the configuration contains credentials to fetch data. These sensitive information shall not -be available unencrypted. - -==== General -We want - -. Data consistency + -- It shall not be possible that we loose data by encryption in any way. + - It must be ensured that the servers are always able to read and write data. - -. Full automated cipher rotation + -There is no need for manual interaction - means it is not necessary to create any cron jobs or -something else to convert non encrypted data to encrypted data or to rotate a password or to -use a new encryption method. - -. Data protection /Privacy policy -- Even for administrators it shall not be possible to fetch the information directly + - _(of course a person who knows the encryption password and has access to the database will always - be able to calculate values - but we separate here between administration and operation inside - this concept, so protection is fully possible)_ -- The data must not be accidentally made available in decrypted form - for example through a REST - call in which the data object is passed along unencrypted. - -. Easy encryption administration - - It shall be possible for an administrator to configure a new cipher entry via REST - -. Secure storage of encryption passwords + - - Encryption passwords are always provided via environment entries, we store always - the environment variable name to use inside the database but never plain values! - -==== Cipher pool -We store the cipher information in a pool table in database: `SCHEDULE_CIPHER_POOL_DATA`. - -[NOTE] -==== -Why in schedule domain and only there? Because it is the responsible domain for the storage. All other -domains should NOT persist this information! -==== - -Here an an overview of the table (names can be different in database): - -[options="header"] -|=== -|id |algorithm | password_source_type |password_source_data| encoding |test_text | test_initial_vector| test_encrypted | creation_timestamp |created_from -//----------------------------------------------------------------------------------------------------------------------------------------------------------------------- -|0 |NO_ENCRYPTION | PLAIN_TEXT | | PLAIN |no-encryption | | no-encryption | 2024-06-24_10:00:01 | null -|1 |AES_GSCM_SIV | ENVIRONMENT_VARIABLE |SECHUB_CRYPTO_P0 | PLAIN |SecHub | easdfa313334 | 53d$125666eeffeded | 2024-06-24_10:05:34 | Admin1 -|2 |AES_GSCM_SIV | ENVIRONMENT_VARIABLE |SECHUB_CRYPTO_P1 | PLAIN |Apfel | fxadsfeec33s | 13x313412124$rfewd | 2024-06-24_11:02:14 | Admin2 -|=== - -*algorithm* - -Algorithm to use in encryption - currently we provide: - -- NONE (only for SQL migration) -- AES_GSCM_SIV - -*password_source_type* - -Currently supported password source types are - -. env + - Here we provide environment variables, the password source data is the name of the environment variable - -We separated source type and source data to be able to provide additional source - e.g. a password fault for the future. - -*password_source_data* - -Depends on the source - -- If source is `env` than this is the name of the environment variable which holds the secret - -====== Usage inside rows - -Inside the encrypted rows we will persist the *pool id* together with an *initial vector* - -*initial vector* -Some algorithm like `AES_GSCM_SIV` do need an initial vector to encrypt secure. The value here is -auto generated by SecHub and is dependent on the algorithm. Because in most cases it shall be random, -SecHub will auto generate a value when it comes to encryption. - -The vector will be stored together with the encrypted data. - -[NOTE] -==== -Maybe it becomes necessary to provide a additional column in future when a new source type is -implemented - e.g a password fault. Maybe a `valid_until` becomes necessary and automatical refresh and more. -But to keep things simple we currently do not provide this. -==== - -====== Administration of cipher pool -*Usecase: Admin adds new cipher pool entry* - -An administrator is able to add a new entry into the cipher pool table via REST API (but there -is no REST call available to remove an entry, this will be done automatically by SecHub when -it becomes possible) - ----- -/api/admin/cipher/add ----- - -Example json body: -[source,json] ----- -{ - "algorithm" : "AES_GSCM_SIV", <1> - "passwordSourceType" : "environment-variable",<2> - "passwordSourceData" : "SECHUB_CRYPTO_P1",<3> - "testText" : "Apfel"<4> - -} ----- -<1> algorithm (possible values are `AES_GSCM_SIV`, `NO_ENCRYPTION` is a algorith definition, but is not accepted by REST api, because designed only for SQL migration) -<2> password source type, supported is currently only `environment-variable`. -<3> the source for the password. For environment variables this must be the name of the variable which is given to Server on server startup -<4> The test text. This value will be encrypted on server side with the given cipher type (e.g. `AES_GSCM_SIV`) - on server side when creating the new pool entry, this text will be stored encrypted inside `test_encrypted` - column (used at server startup to ensure variables are correct set and it is possible to encrypt data) - -*Usecase: Admin lists all current cipher pool entries* - ----- -/api/admin/cipher/list ----- - -Example result: - -[source,json] ----- -{ - { - "id": "0", - "algorithm" : "NONE", - "envVar" : null, - "testText" : null, - "created" : "2024-06-24_10:00:01", - "initialVector" : "gen-uuid1" - }, - { - "id": "1", - "algorithm" : "AES_GSCM_SIV", - "envVar" : "SECHUB_CRYPTO_P0", - "testText" : "SecHub1", - "testEncrypted" : "53d$125666eeffeded", - "created" : "2024-06-24_10:05:34", - "initialVector" : "gen-uuid2" - }, - { - "id": "2", - "algorithm" : "AES_GSCM_SIV", - "envVar" : "SECHUB_CRYPTO_P1", - "testText" : "13x313412124$rfewd", - "created" : "2024-06-24_11:02:14", - "initialVector" : "gen-uuid3" - } -} ----- - -===== Server startup blocking - -A SecHub server will stop on startup phase when - -- one of the entries inside the cipher pool cannot be handled by this server. + -This ensures that every new started server is able to handle all of them / is always readable. - -===== Auto cleanup inside Cipher pool -For the <> mechanism the use case with id: `UC_SCHEDULE_AUTO_CLEANUP_EXECUTION` -is extended to cleanup not only old jobs, but also to cleanup cipher pool entries which are no longer used -by any job - except the newest one which must be kept always. - -When the entry is deleted, a log entry at info level is created containing the complete information about the -deleted log entry is done. - -==== Scheduler jobs and encryption -===== Create new job -When a new job is created by scheduler, the scheduler will store the new job with latest supported cipher pool id -and use the necessary encryption here. - -- `SCHEDULE_SECHUB_JOB` has a column `cipher_pool_id` to store this - -==== Automatic job encryption updates -===== Canceled or ended jobs get auto encryption update -The `SchedulerJobEncryptionUpdateTriggerService` is fetches periodically (on every SecHub server cluster member) -all jobs jobs which are in execution state `ENDED` (means failed or success) or `CANCELED` which have not the -latest cipher from pool and will do an encryption conversion here. - -===== New / non approved jobs are handled by auto cleanup -Because there is the possibility that there are jobs which are created, but never approved, those jobs must be -handled as well. But we must ensure that we have no race conditions here (e.g. the job gets approved and job starts -running while the encryption data is changed). - -To keep this as simple as possible and to ensure we have no race conditions, we just do not handle them directly, -but let this be done by the <> mechanism, which will delete older jobs after a -period of time automatically (see `ScheduleAutoCleanupService` for details). - -==== Handling server update/migration -Old server versions do not have the encryption field inside the scheduler job table or the cipher pool table. - -Our SQL migration scripts will initialize the cipher pool with a NONE entry (and id 0) and add the information -to all existing jobs. - -==== Secure per default -When a {sechub} server starts and the cipher pool table does not contain an entry which is not a `NONE` -type, a new entry is added automatically with `AES_GSCM_SIV` and the environment entry -`SECHUB_CRYPTO_P0`. It is also checked in this case that the environment variable is not empty -- otherwise server will not start. - -[NOTE] -==== -`SECHUB_CRYPTO_P0` is special treated for integration tests! Here the spring value `sechub.crypto.p0` is possible -as well. This will be handled by registration process at serve startup where the supported parts -from cipher pool are determined. -==== - - -==== Handling sensitive data at runtime -JVM crash dumps contain string information. To handle this risk the SecHubConfiguration model does -contain sensitive data like remote data credentials and webScan login information always as sealed -objects. The data is converted to plain text only when needed. - -When we have PDS data transfer we use directly json, means the sealed object is automatically unsealed. -Usage of direct json data shoud be reduced as much as as possible to avoid dump scenario. - -[IMPORTANT] -==== -As long as DDD is running inside one JVM using sealed objects is no problem at all at SecHub side, -because it can be unsealed everywhere inside the JVM. But if we change our -<> and seperate {sechub} domain parts -standalone, there will be a need to handle this similar to PDS communication (means json) because different JVMs -would be used as well. -==== - - - -===== Special usecas -====== For administrators and support -Because it can happen that an administrator is asked by a user to help with configuration problems, -it shall be possible to fetch a scheduler sechub configuration by administrators as plain text (json). - -// TODO 2024-06-27, de-jcup: maybe asterisk handling like done for secret-scan secret results (configurable) -But the sealed objects inside this configuration object shall be replaced with string data which contains only -asterisks. - -This is audit logged, means it is clear which person has accessed the configuration file. - -====== Treatment of meta data inside SecHubConfiguration -SecHubConfiguration model is encrypted, because it can contain sensitive data. E.g. inside remote data -section. - -There exists a REST endpoint which gives users the possiblity to fetch job information, together with -the meta data defined inside the {sechub} configuration. To obtain this information, the configuration -will be encrypted at runtime and the meta data are resolved. Because meta data shall not contain any -sensitive information, this will not be audit logged. - -==== Diagrams -===== Schedule encryption -plantuml::diagrams/diagram_encryption_sechub_config.puml[] - -==== Important infos about migration - -====== Server 1.10.0 to 2.0.0 - -- Normally we a have zero downtime and rolling updates with k8s and SecHub. But here we need one! - Reason: We must ensure there is no old server running which creates new jobs with - unencrypted config part inside. To prevent such a situation (if somebody doest still a rolling update, - we have changed the column name inside `schedule_sechub_job` from configuration to `unencrypted_configuration`. - Old servers will no longer be able to write this and a SQL error will happen. - - -- K8s deployment - diff --git a/sechub-doc/src/docs/asciidoc/documents/shared/concepts/concept_sechub_data_encryption.adoc b/sechub-doc/src/docs/asciidoc/documents/shared/concepts/concept_sechub_data_encryption.adoc new file mode 100644 index 0000000000..c37641bc77 --- /dev/null +++ b/sechub-doc/src/docs/asciidoc/documents/shared/concepts/concept_sechub_data_encryption.adoc @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: MIT +[[section-shared-concepts-sechub-data-encryption]] +In {sechub} we have some sensitive data we want to be encrypted. For example: Inside remote data +section the configuration contains credentials to fetch data. These sensitive information shall +be always encrypted. + +==== General +We want + +. Data consistency + +- It shall not be possible that we loose data by encryption in any way. + + It must be ensured that the servers are always able to read and write data. + +. Full automated cipher rotation + +There is no need for manual interaction - means it is not necessary to create any cron jobs or +something else to convert non encrypted data to encrypted data or to rotate a password or to +use a new encryption method. + +. Data protection /Privacy policy +- Even for administrators it shall not be possible to fetch the information directly + + _(of course a person who knows the encryption password and has access to the database will always + be able to calculate values - but we separate here between administration and operation inside + this concept, so protection is fully possible)_ +- The data must not be accidentally made available in decrypted form - for example through a REST + call in which the data object is passed along unencrypted. + +. Easy encryption administration + - It shall be possible for an administrator to configure a new cipher entry via REST + +. Secure storage of encryption passwords + + - Encryption passwords are always provided via environment entries, we store always + the environment variable name to use inside the database but never plain values! + +==== Server startup +A {sechub} server will stop on startup phase when one of the entries inside the cipher pool cannot be handled by this server. + +This ensures that every new started server is able to handle all of them / is always readable. + +==== Administration +[[section-shared-concepts-sechub-data-encryption-rotation]] +===== Encryption rotation + +An administrator is able to start encryption rotation via REST. This will + +- use new encryption setup for all new data +- automatically convert existing encrypted data with new encryption setup in background + +===== Encryption status +An administrator is able to fetch encryption status from {sechub} server. All domains which are +doing data encryption add their current status information into result. + +===== Cleanup old encryption setup +<> automatically removes old information. +This means that old encrypted information that cannot be updated for some reason may eventually +disappear and old encryption configurations are then no longer needed and can be removed. + +To fully automate this, after the respective Auto Cleanup, the domains are always checked for encryption configurations that are no longer used and these are then automatically removed (except for the most recent encryption configuration). + + +[IMPORTANT] +==== +If you have setup auto cleanup to 0 days, the auto cleanup is disabled completely and +unused encryption setup will also not be removed. +==== + +==== Scheduler +Inside the schedule domain, the sensitive information is the sechub job configuration. + +===== Database +====== Table +We store the cipher information inside table: `SCHEDULE_CIPHER_POOL_DATA`. + +[NOTE] +==== +Why in schedule domain and only there? Because it is the responsible domain for the storage. All other +domains may NEVER persist this information (for `PDS` the configuration will be sent from SecHub +and stored at `PDS` side encrypted as well) +==== + +Here an an overview of the table (names can be different in database): + +[options="header"] +|=== +|id |algorithm | password_source_type |password_source_data| encoding |test_text | test_initial_vector| test_encrypted | creation_timestamp |created_from +//----------------------------------------------------------------------------------------------------------------------------------------------------------------------- +|0 |NO_ENCRYPTION | PLAIN_TEXT | | PLAIN |no-encryption | | no-encryption | 2024-06-24_10:00:01 | null +|1 |AES_GCM_SIV_128| ENVIRONMENT_VARIABLE |SECHUB_CRYPTO_P0 | PLAIN |SecHub | easdfa313334 | 53d$125666eeffeded | 2024-06-24_10:05:34 | Admin1 +|2 |AES_GCM_SIV_256| ENVIRONMENT_VARIABLE |SECHUB_CRYPTO_P1 | PLAIN |Apfel | fxadsfeec33s | 13x313412124$rfewd | 2024-06-24_11:02:14 | Admin2 +|=== + + +*algorithm* + +Algorithm to use in encryption - currently we provide: + +- NONE (means not encrypted!) +- AES_GCM_SIV_128 +- AES_GCM_SIV_256 + +*password_source_type* + +Currently supported password source types are + +. ENVIRONMENT_VARIABLE + + Here we provide environment variables, the password source data is the name of the environment variable +. NONE + + No password - only allowed for `NONE` algorithm + + +We separated source type and source data to be able to provide additional source - e.g. a password fault for the future. + +*password_source_data* + +Depends on the source + +- If source is `env` than this is the name of the environment variable which holds the secret + +====== Usage inside rows + +Inside the encrypted rows we will persist the *pool id* together with an *initial vector* + +*initial vector* +Some algorithm like `AES_GSCM_SIV` do need an initial vector to encrypt secure. The value here is +auto generated by SecHub and is dependent on the algorithm. + +SecHub will always auto generate a dedicate value when it comes to encryption and the vector +will be stored together with the encrypted data. If the initial vector is changed, the row cannot +be decrypted, even when the secret key is known! + +==== Handling server updates +===== {sechub} server 1.x to 2.x +Old server versions do not have the encryption field inside the scheduler job table or the cipher pool table. + +Our SQL migration scripts will initialize scheduler cipher pool table on creation time with a +`NONE` entry (pool id = 0). This is encryption setup (meaning no encryption) will be added +to all existing jobs. This behavior happens for new + +We want to have zero downtime and rolling updates with k8s and SecHub. To provide this, +it must be ensured, that there is no old server running which creates new jobs with +plain text configurations while update is running. To prevent such a situation +the column name inside `schedule_sechub_job` have been renamed from `configuration` to `unencrypted_configuration`. +If there appears any race conditions, old servers would no longer be able to write data and a +SQL error would happen. + +==== Handling server downgrade +===== {sechub} server 2.x to 1.x +For a downgrade from {sechub} server V2.x to V1.x it is necessary to ensure, that all data is +encrypted with `NONE` cipher type (can be done by encryption rotation). When ensured that everything +is "encrypted" with this cipher type, the old server version can be deployed/used and migration +is automatically done as usual. + + +==== Handling sensitive data at runtime +JVM crash dumps contain string information. Classes containing sensitive information shall +store such information inside sealed objects. + +==== Handling metadata from job configuration +The {secHub} configuration is encrypted, because it can contain sensitive data. E.g. when defining a remote data +section. + +There exists a REST endpoint which gives users the possiblity to fetch job information, together with +the meta data defined inside the {sechub} configuration. + +To obtain this information, the configuration will be decrypted temporary at runtime and the meta +data are resolved and returned. + +Because meta data shall not contain any sensitive information, this will not be audit logged. + + +==== Diagrams +===== Schedule encryption +plantuml::diagrams/diagram_encryption_sechub_config.puml[] + +==== Migration issues + +- diff --git a/sechub-server/src/main/resources/db/migration/common/U29__encryption_common.sql b/sechub-server/src/main/resources/db/migration/common/U29__encryption_common.sql new file mode 100644 index 0000000000..d49159b18f --- /dev/null +++ b/sechub-server/src/main/resources/db/migration/common/U29__encryption_common.sql @@ -0,0 +1,10 @@ +-- SPDX-License-Identifier: MIT +ALTER TABLE schedule_sechub_job DROP COLUMN encrypted_configuration bytea; +ALTER TABLE schedule_sechub_job DROP COLUMN encrypt_initial_vector bytea; +ALTER TABLE schedule_sechub_job DROP COLUMN encrypt_pool_data_id integer; + +DROP TABLE IF EXISTS schedule_cipher_pool_data; + +ALTER TABLE adm_job_information ADD COLUMN configuration varchar(8912); +ALTER TABLE scan_project_log ADD COLUMN config varchar(8912); +ALTER TABLE scan_report ADD COLUMN config varchar(8912); diff --git a/sechub-server/src/main/resources/db/migration/common/U31__encryption_drop_unencrypted_config.sql b/sechub-server/src/main/resources/db/migration/common/U31__encryption_drop_unencrypted_config.sql new file mode 100644 index 0000000000..5be7dc5933 --- /dev/null +++ b/sechub-server/src/main/resources/db/migration/common/U31__encryption_drop_unencrypted_config.sql @@ -0,0 +1,2 @@ +-- SPDX-License-Identifier: MIT +ALTER TABLE schedule_sechub_job DROP COLUMN unencrypted_configuration; \ No newline at end of file diff --git a/sechub-server/src/main/resources/db/migration/h2/U30__encryption_first_cipher_h2.sql b/sechub-server/src/main/resources/db/migration/h2/U30__encryption_first_cipher_h2.sql new file mode 100644 index 0000000000..a06266efc1 --- /dev/null +++ b/sechub-server/src/main/resources/db/migration/h2/U30__encryption_first_cipher_h2.sql @@ -0,0 +1,8 @@ +-- SPDX-License-Identifier: MIT + +-- In postgres we do a migration +-- But here, for h2, we do not migrate old data, because +-- h2 is only for testing! +-- Means no job migration done here. + +DELETE FROM schedule_cipher_pool_data; \ No newline at end of file diff --git a/sechub-server/src/main/resources/db/migration/postgres/U30__encryption_first_cipher_postgres.sql b/sechub-server/src/main/resources/db/migration/postgres/U30__encryption_first_cipher_postgres.sql new file mode 100644 index 0000000000..420b5a3c0e --- /dev/null +++ b/sechub-server/src/main/resources/db/migration/postgres/U30__encryption_first_cipher_postgres.sql @@ -0,0 +1,7 @@ +-- SPDX-License-Identifier: MIT + +-- convert to var char - we expect unencrypted_configuration is only "encrypted" with 'NONE' +update schedule_sechub_job ssj set + configuration = convert_from(encrypted_configuration, 'UTF8') + +DELETE FROM schedule_cipher_pool_data;