Skip to content
This repository has been archived by the owner on Sep 15, 2023. It is now read-only.

Commit

Permalink
Merge pull request #24 from admin-ch/feature/certificate-light
Browse files Browse the repository at this point in the history
ensure manually added certificates are not removed by sync
  • Loading branch information
ubhaller authored Jul 6, 2021
2 parents 7f4bc52 + be08acf commit e079ed9
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public interface VerifierDataService {
public void insertCSCAs(List<DbCsca> cscas);

/**
* removes all csas with key ids in the given list
* removes all csas with key ids in the given list that haven't been added manually
*
* @param keyIds
* @return number of removed CSCAs
Expand All @@ -44,10 +44,10 @@ public interface VerifierDataService {
/** inserts the given DSC into the db */
public void insertDSCs(List<DbDsc> dsc);

/** removes all DSCs with key ids not in the given list */
/** removes all DSCs with key ids not in the given list that haven't been added manually */
public int removeDSCsNotIn(List<String> keyIdsToKeep);

/** removes all DSCs signed by a CSCA in the given list */
/** removes all DSCs signed by a CSCA in the given list that haven't been added manually */
public int removeDSCsWithCSCAIn(List<String> cscaKidsToRemove);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import ch.admin.bag.covidcertificate.backend.verifier.data.VerifierDataService;
import ch.admin.bag.covidcertificate.backend.verifier.data.mapper.CSCARowMapper;
import ch.admin.bag.covidcertificate.backend.verifier.data.mapper.ClientCertRowMapper;
import ch.admin.bag.covidcertificate.backend.verifier.model.CertSource;
import ch.admin.bag.covidcertificate.backend.verifier.model.cert.CertFormat;
import ch.admin.bag.covidcertificate.backend.verifier.model.cert.ClientCert;
import ch.admin.bag.covidcertificate.backend.verifier.model.cert.db.DbCsca;
Expand Down Expand Up @@ -72,10 +73,13 @@ public void insertCSCAs(List<DbCsca> cscas) {
@Transactional
public int removeCSCAs(List<String> keyIds) {
if (!keyIds.isEmpty()) {
var sql = "delete from t_country_specific_certificate_authority";
var sql =
"delete from t_country_specific_certificate_authority"
+ " where key_id in (:kids)"
+ " and source != :manual";
final var params = new MapSqlParameterSource();
sql += " where key_id in (:kids)";
params.addValue("kids", keyIds);
params.addValue("manual", CertSource.MANUAL.name());
return jt.update(sql, params);
} else {
return 0;
Expand Down Expand Up @@ -117,8 +121,9 @@ public int removeDSCsNotIn(List<String> keyIdsToKeep) {
var sql = "delete from t_document_signer_certificate";
final var params = new MapSqlParameterSource();
if (!keyIdsToKeep.isEmpty()) {
sql += " where key_id not in (:kids)";
sql += " where key_id not in (:kids) and source != :manual";
params.addValue("kids", keyIdsToKeep);
params.addValue("manual", CertSource.MANUAL.name());
}
return jt.update(sql, params);
}
Expand All @@ -127,9 +132,13 @@ public int removeDSCsNotIn(List<String> keyIdsToKeep) {
@Transactional
public int removeDSCsWithCSCAIn(List<String> cscaKidsToRemove) {
if (!cscaKidsToRemove.isEmpty()) {
var sql = "delete from t_document_signer_certificate where fk_csca_id in (:fk_csca_id)";
var sql =
"delete from t_document_signer_certificate"
+ " where fk_csca_id in (:fk_csca_id)"
+ " and source != :manual";
final var params = new MapSqlParameterSource();
params.addValue("fk_csca_id", findCscaPksForKids(cscaKidsToRemove));
params.addValue("manual", CertSource.MANUAL.name());
return jt.update(sql, params);
} else {
return 0;
Expand Down Expand Up @@ -211,6 +220,7 @@ private MapSqlParameterSource getCSCAParams(DbCsca dbCsca) {
params.addValue("certificate_raw", dbCsca.getCertificateRaw());
params.addValue("origin", dbCsca.getOrigin());
params.addValue("subject_principal_name", dbCsca.getSubjectPrincipalName());
params.addValue("source", CertSource.SYNC.name());
return params;
}

Expand All @@ -228,6 +238,7 @@ private MapSqlParameterSource getDSCParams(DbDsc dbDsc) {
params.addValue("crv", dbDsc.getCrv());
params.addValue("x", dbDsc.getX());
params.addValue("y", dbDsc.getY());
params.addValue("source", CertSource.SYNC.name());
return params;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Created by Ubique Innovation AG
* https://www.ubique.ch
* Copyright (c) 2021. All rights reserved.
*/

alter table t_country_specific_certificate_authority add column source character varying(10);
update t_country_specific_certificate_authority set source = 'SYNC';
alter table t_country_specific_certificate_authority alter column source set not null;
update t_country_specific_certificate_authority set source = 'MANUAL' where origin = 'CH';

alter table t_document_signer_certificate add column source character varying(10);
update t_document_signer_certificate set source = 'SYNC';
alter table t_document_signer_certificate alter column source set not null;
update t_document_signer_certificate set source = 'MANUAL' where origin = 'CH';
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Created by Ubique Innovation AG
* https://www.ubique.ch
* Copyright (c) 2021. All rights reserved.
*/

alter table t_country_specific_certificate_authority add column source character varying(10);
update t_country_specific_certificate_authority set source = 'SYNC';
alter table t_country_specific_certificate_authority alter column source set not null;
update t_country_specific_certificate_authority set source = 'MANUAL' where origin = 'CH';

alter table t_document_signer_certificate add column source character varying(10);
update t_document_signer_certificate set source = 'SYNC';
alter table t_document_signer_certificate alter column source set not null;
update t_document_signer_certificate set source = 'MANUAL' where origin = 'CH';
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

import ch.admin.bag.covidcertificate.backend.verifier.data.config.FlywayConfig;
import ch.admin.bag.covidcertificate.backend.verifier.data.config.TestConfig;
import javax.sql.DataSource;
import javax.validation.constraints.NotNull;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
Expand All @@ -20,6 +25,7 @@
@ContextConfiguration(initializers = BaseDataServiceTest.DockerPostgresDataSourceInitializer.class)
@SpringBootTest(classes = {TestConfig.class, FlywayConfig.class})
@Testcontainers
@TestInstance(Lifecycle.PER_CLASS)
public abstract class BaseDataServiceTest {

public static PostgreSQLContainer<?> postgreSQLContainer =
Expand All @@ -44,4 +50,12 @@ public void initialize(@NotNull final ConfigurableApplicationContext application
"spring.datasource.password=" + postgreSQLContainer.getPassword());
}
}

@Autowired DataSource dataSource;
protected NamedParameterJdbcTemplate jt;

@BeforeAll
void setup() {
this.jt = new NamedParameterJdbcTemplate(dataSource);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import ch.admin.bag.covidcertificate.backend.verifier.model.CertSource;
import ch.admin.bag.covidcertificate.backend.verifier.model.cert.Algorithm;
import ch.admin.bag.covidcertificate.backend.verifier.model.cert.CertFormat;
import ch.admin.bag.covidcertificate.backend.verifier.model.cert.db.DbCsca;
Expand All @@ -14,6 +15,7 @@
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.transaction.annotation.Transactional;

class VerifierDataServiceTest extends BaseDataServiceTest {
Expand Down Expand Up @@ -43,6 +45,27 @@ void removeCscasNotInTest() {
verifierDataService.insertCSCAs(Collections.singletonList(getDefaultCSCA(1, "CH")));
verifierDataService.removeCSCAs(Collections.singletonList("keyid_0"));
assertEquals(1, verifierDataService.findCSCAs("CH").size());

// verify manual doesnt get removed
updateSourceForAllCscas(CertSource.MANUAL);
verifierDataService.removeCSCAs(Collections.singletonList("keyid_1"));
assertEquals(1, verifierDataService.findCSCAs("CH").size());

updateSourceForAllCscas(CertSource.SYNC);
verifierDataService.removeCSCAs(Collections.singletonList("keyid_1"));
assertEquals(0, verifierDataService.findCSCAs("CH").size());
}

private void updateSourceForAllCscas(CertSource source) {
jt.update(
"update t_country_specific_certificate_authority set source = :source",
new MapSqlParameterSource("source", source.name()));
}

private void updateSourceForAllDscs(CertSource source) {
jt.update(
"update t_document_signer_certificate set source = :source",
new MapSqlParameterSource("source", source.name()));
}

@Test
Expand Down Expand Up @@ -100,6 +123,15 @@ void removeDscsNotInTest() {
verifierDataService.insertDSCs(List.of(rsaDsc, ecDsc));
verifierDataService.removeDSCsNotIn(Collections.singletonList(rsaDsc.getKeyId()));
assertEquals(1, verifierDataService.findActiveDSCKeyIds(nowPlus1Min()).size());

// verify manual doesnt get removed
updateSourceForAllDscs(CertSource.MANUAL);
verifierDataService.removeDSCsNotIn(Collections.singletonList(ecDsc.getKeyId()));
assertEquals(1, verifierDataService.findActiveDSCKeyIds(nowPlus1Min()).size());

updateSourceForAllDscs(CertSource.SYNC);
verifierDataService.removeDSCsNotIn(Collections.singletonList(ecDsc.getKeyId()));
assertEquals(0, verifierDataService.findActiveDSCKeyIds(nowPlus1Min()).size());
}

@Test
Expand All @@ -118,6 +150,15 @@ void removeDscsWithCSCAIn() {
assertEquals(2, verifierDataService.findActiveDSCKeyIds(nowPlus1Min()).size());
verifierDataService.removeDSCsWithCSCAIn(List.of(cscas.get(0).getKeyId()));
assertEquals(1, verifierDataService.findActiveDSCKeyIds(nowPlus1Min()).size());

// verify manual doesnt get removed
updateSourceForAllDscs(CertSource.MANUAL);
verifierDataService.removeDSCsWithCSCAIn(List.of(cscas.get(1).getKeyId()));
assertEquals(1, verifierDataService.findActiveDSCKeyIds(nowPlus1Min()).size());

updateSourceForAllDscs(CertSource.SYNC);
verifierDataService.removeDSCsWithCSCAIn(List.of(cscas.get(1).getKeyId()));
assertEquals(0, verifierDataService.findActiveDSCKeyIds(nowPlus1Min()).size());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2021 Ubique Innovation AG <https://www.ubique.ch>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* SPDX-License-Identifier: MPL-2.0
*/

package ch.admin.bag.covidcertificate.backend.verifier.model;

public enum CertSource {
MANUAL,
SYNC;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class ClientCert {

@Documentation(
description =
"either 'sig' (all) or one or more of: 'r' (recovery), 't' (test), 'v' (vaccine)",
"either 'sig' (all) or one or more of: 'r' (recovery), 't' (test), 'v' (vaccine), 'l' (light)",
example = "sig")
private String use;

Expand Down

0 comments on commit e079ed9

Please sign in to comment.