From fe7f9e3e1e07f38e97c67fd85d83e042f379b447 Mon Sep 17 00:00:00 2001 From: Marco Fargetta Date: Tue, 22 Oct 2024 10:28:53 +0200 Subject: [PATCH 1/2] Add a new sequential number generator: legacy2 The current generator has a problem with converting from hex to decimal the range boundaries creating gaps between ranges. This a problem when third parties tools are used to with certificates because contiguous range are expected. This commit introduce the generator legacy2. This uses same configuration parameter but hex value are specified by the prefix '0x'. When value are written to the configuration value it is possible to set the radix with the options: - dbs.cert.id.radix (default to 16) - dbs.key.id.radix (default to 16) - dbs.request.id.radix (default to 10) Additionally, the new command `pki-server -id-generator-*` has been added to migrate from the legacy generator to the legacy2 or to random. --- .../netscape/cmscore/dbs/CRLRepository.java | 32 +- .../cmscore/dbs/CertificateRepository.java | 53 ++- .../org/dogtagpki/server/ca/cli/CACLI.java | 1 + .../org/dogtagpki/server/ca/cli/CAIdCLI.java | 19 ++ .../server/ca/cli/CAIdGeneratorCLI.java | 21 ++ .../server/ca/cli/CAIdGeneratorUpdateCLI.java | 53 +++ .../server/ca/cli/CARangeUpdateCLI.java | 4 +- .../netscape/cmscore/dbs/KeyRepository.java | 53 ++- .../org/dogtagpki/server/kra/cli/KRACLI.java | 1 + .../dogtagpki/server/kra/cli/KRAIdCLI.java | 19 ++ .../server/kra/cli/KRAIdGeneratorCLI.java | 18 + .../server/kra/cli/KRARangeUpdateCLI.java | 2 +- .../kra/cli/kraIdGeneratorUpdateCLI.java | 45 +++ base/server/etc/default.cfg | 6 +- base/server/python/pki/server/cli/ca.py | 2 + base/server/python/pki/server/cli/id.py | 187 +++++++++++ .../python/pki/server/deployment/__init__.py | 24 +- base/server/python/pki/server/subsystem.py | 22 +- .../servlet/csadmin/UpdateNumberRange.java | 46 ++- .../netscape/cmscore/apps/DatabaseConfig.java | 18 + .../cmscore/dbs/ReplicaIDRepository.java | 30 +- .../com/netscape/cmscore/dbs/Repository.java | 29 +- .../cmscore/request/RequestRepository.java | 54 ++- .../dogtagpki/server/cli/SubsystemCLI.java | 16 + .../cli/SubsystemIdGeneratorUpdateCLI.java | 310 ++++++++++++++++++ .../server/cli/SubsystemRangeUpdateCLI.java | 38 ++- .../cmscore/test/CMSBaseTestHelper.java | 8 + 27 files changed, 1010 insertions(+), 101 deletions(-) create mode 100644 base/ca/src/main/java/org/dogtagpki/server/ca/cli/CAIdCLI.java create mode 100644 base/ca/src/main/java/org/dogtagpki/server/ca/cli/CAIdGeneratorCLI.java create mode 100644 base/ca/src/main/java/org/dogtagpki/server/ca/cli/CAIdGeneratorUpdateCLI.java create mode 100644 base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRAIdCLI.java create mode 100644 base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRAIdGeneratorCLI.java create mode 100644 base/kra/src/main/java/org/dogtagpki/server/kra/cli/kraIdGeneratorUpdateCLI.java create mode 100644 base/server/python/pki/server/cli/id.py create mode 100644 base/server/src/main/java/org/dogtagpki/server/cli/SubsystemIdGeneratorUpdateCLI.java diff --git a/base/ca/src/main/java/com/netscape/cmscore/dbs/CRLRepository.java b/base/ca/src/main/java/com/netscape/cmscore/dbs/CRLRepository.java index e740cee279f..b510adbdaa6 100644 --- a/base/ca/src/main/java/com/netscape/cmscore/dbs/CRLRepository.java +++ b/base/ca/src/main/java/com/netscape/cmscore/dbs/CRLRepository.java @@ -49,7 +49,7 @@ public class CRLRepository extends Repository { * Constructs a CRL repository. */ public CRLRepository(DBSubsystem dbSubsystem) { - super(dbSubsystem, 10); + super(dbSubsystem, DEC); } @Override @@ -67,18 +67,10 @@ public void init() throws Exception { rangeDN = dbConfig.getRequestRangeDN() + "," + dbSubsystem.getBaseDN(); logger.info("CRLRepository: - range DN: " + rangeDN); - minSerialName = DatabaseConfig.MIN_REQUEST_NUMBER; - String minSerial = dbConfig.getBeginRequestNumber(); - if (minSerial != null) { - mMinSerialNo = new BigInteger(minSerial, mRadix); - } + mMinSerialNo = dbConfig.getBigInteger(DatabaseConfig.MIN_REQUEST_NUMBER, null); logger.info("CRLRepository: - min serial: " + mMinSerialNo); - maxSerialName = DatabaseConfig.MAX_REQUEST_NUMBER; - String maxSerial = dbConfig.getEndRequestNumber(); - if (maxSerial != null) { - mMaxSerialNo = new BigInteger(maxSerial, mRadix); - } + mMaxSerialNo = dbConfig.getBigInteger(DatabaseConfig.MAX_REQUEST_NUMBER, null); logger.info("CRLRepository: - max serial: " + mMaxSerialNo); nextMinSerialName = DatabaseConfig.NEXT_MIN_REQUEST_NUMBER; @@ -86,7 +78,7 @@ public void init() throws Exception { if (nextMinSerial == null || nextMinSerial.equals("-1")) { mNextMinSerialNo = null; } else { - mNextMinSerialNo = new BigInteger(nextMinSerial, mRadix); + mNextMinSerialNo = dbConfig.getBigInteger(DatabaseConfig.NEXT_MIN_REQUEST_NUMBER, null); } logger.info("CRLRepository: - next min serial: " + mNextMinSerialNo); @@ -95,19 +87,15 @@ public void init() throws Exception { if (nextMaxSerial == null || nextMaxSerial.equals("-1")) { mNextMaxSerialNo = null; } else { - mNextMaxSerialNo = new BigInteger(nextMaxSerial, mRadix); + mNextMaxSerialNo = dbConfig.getBigInteger(DatabaseConfig.NEXT_MAX_REQUEST_NUMBER, null); } logger.info("CRLRepository: - next max serial: " + mNextMaxSerialNo); - String lowWaterMark = dbConfig.getRequestLowWaterMark(); - if (lowWaterMark != null) { - mLowWaterMarkNo = new BigInteger(lowWaterMark, mRadix); - } - - String incrementNo = dbConfig.getRequestIncrement(); - if (incrementNo != null) { - mIncrementNo = new BigInteger(incrementNo, mRadix); - } + mLowWaterMarkNo = dbConfig.getBigInteger(DatabaseConfig.REQUEST_LOW_WATER_MARK, null); + logger.debug("CRLRepository: - low water mark serial: " + mNextMaxSerialNo); + + mIncrementNo = dbConfig.getBigInteger(DatabaseConfig.REQUEST_INCREMENT, null); + logger.debug("CRLRepository: - increment serial: " + mIncrementNo); /* DBRegistry reg = dbService.getRegistry(); diff --git a/base/ca/src/main/java/com/netscape/cmscore/dbs/CertificateRepository.java b/base/ca/src/main/java/com/netscape/cmscore/dbs/CertificateRepository.java index 471e160d699..4ec6e31d7fd 100644 --- a/base/ca/src/main/java/com/netscape/cmscore/dbs/CertificateRepository.java +++ b/base/ca/src/main/java/com/netscape/cmscore/dbs/CertificateRepository.java @@ -80,6 +80,7 @@ public class CertificateRepository extends Repository { private static final BigInteger BI_MINUS_ONE = BigInteger.ONE.negate(); public static final String PROP_CERT_ID_GENERATOR = "cert.id.generator"; + public static final String PROP_CERT_ID_RADIX = "cert.id.radix"; public static final String DEFAULT_CERT_ID_GENERATOR = "legacy"; public static final String PROP_CERT_ID_LENGTH = "cert.id.length"; @@ -103,8 +104,15 @@ public CertificateRepository( SecureRandom secureRandom, DBSubsystem dbSubsystem) { - super(dbSubsystem, 16); - + super(dbSubsystem, HEX); + DatabaseConfig dbc = dbSubsystem.getDBConfigStore(); + try { + this.mRadix = dbc.getInteger(PROP_CERT_ID_RADIX, HEX); + logger.debug("CertificateRepository: number radix {}", this.mRadix); + + } catch (EBaseException ex) { + logger.debug("CertificateRepository: error reading number radix config, using default {} for ", HEX); + } this.secureRandom = secureRandom; } @@ -126,12 +134,51 @@ public void init() throws Exception { idLength = mDBConfig.getInteger(PROP_CERT_ID_LENGTH, DEFAULT_CERT_ID_LENGTH); logger.debug("CertificateRepository: - cert ID length: " + idLength); - + } else if (idGenerator == IDGenerator.LEGACY_2) { + initLegacy2Generator(); } else { initLegacyGenerator(); } } + protected void initLegacy2Generator() throws EBaseException { + + rangeDN = mDBConfig.getSerialRangeDN() + "," + dbSubsystem.getBaseDN(); + logger.debug("CertificateRepository: - range DN: " + rangeDN); + + minSerialName = DatabaseConfig.MIN_SERIAL_NUMBER; + mMinSerialNo = mDBConfig.getBigInteger(minSerialName, null); + logger.debug("CertificateRepository: - min serial: " + mMinSerialNo); + + maxSerialName = DatabaseConfig.MAX_SERIAL_NUMBER; + mMaxSerialNo = mDBConfig.getBigInteger(maxSerialName, null); + logger.debug("CertificateRepository: - max serial: " + mMaxSerialNo); + + nextMinSerialName = DatabaseConfig.NEXT_MIN_SERIAL_NUMBER; + String nextMinSerial = mDBConfig.getNextBeginSerialNumber(); + if (nextMinSerial == null || nextMinSerial.equals("-1")) { + mNextMinSerialNo = null; + } else { + mNextMinSerialNo = mDBConfig.getBigInteger(DatabaseConfig.NEXT_MIN_SERIAL_NUMBER, null); + } + logger.debug("CertificateRepository: - next min serial: " + mNextMinSerialNo); + + nextMaxSerialName = DatabaseConfig.NEXT_MAX_SERIAL_NUMBER; + String nextMaxSerial = mDBConfig.getNextEndSerialNumber(); + if (nextMaxSerial == null || nextMaxSerial.equals("-1")) { + mNextMaxSerialNo = null; + } else { + mNextMaxSerialNo = mDBConfig.getBigInteger(DatabaseConfig.NEXT_MAX_SERIAL_NUMBER, null); + } + logger.debug("CertificateRepository: - next max serial: " + mNextMaxSerialNo); + + mLowWaterMarkNo = mDBConfig.getBigInteger(DatabaseConfig.SERIAL_LOW_WATER_MARK, null); + logger.debug("CertificateRepository: - low water mark serial: " + mNextMaxSerialNo); + + mIncrementNo = mDBConfig.getBigInteger(DatabaseConfig.SERIAL_INCREMENT, null); + logger.debug("CertificateRepository: - increment serial: " + mIncrementNo); + } + public void initLegacyGenerator() throws Exception { rangeDN = mDBConfig.getSerialRangeDN() + "," + dbSubsystem.getBaseDN(); diff --git a/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CACLI.java b/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CACLI.java index 6c32799000b..0adb076183e 100644 --- a/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CACLI.java +++ b/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CACLI.java @@ -36,6 +36,7 @@ public CACLI(CLI parent) { addModule(new SubsystemGroupCLI(this)); addModule(new CAProfileCLI(this)); addModule(new CARangeCLI(this)); + addModule(new CAIdCLI(this)); addModule(new SubsystemUserCLI(this)); addModule(new SDCLI(this)); } diff --git a/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CAIdCLI.java b/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CAIdCLI.java new file mode 100644 index 00000000000..899e7bb77d2 --- /dev/null +++ b/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CAIdCLI.java @@ -0,0 +1,19 @@ +// +// Copyright Red Hat, Inc. +// +// SPDX-License-Identifier: GPL-2.0-or-later +// +package org.dogtagpki.server.ca.cli; + +import org.dogtagpki.cli.CLI; + +/** + * @author Marco Fargetta {@literal } + */ +public class CAIdCLI extends CLI { + public CAIdCLI(CLI parent) { + super("id", "CA id generator management commands", parent); + + addModule(new CAIdGeneratorCLI(this)); + } +} diff --git a/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CAIdGeneratorCLI.java b/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CAIdGeneratorCLI.java new file mode 100644 index 00000000000..b74b8832414 --- /dev/null +++ b/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CAIdGeneratorCLI.java @@ -0,0 +1,21 @@ +// +// Copyright Red Hat, Inc. +// +// SPDX-License-Identifier: GPL-2.0-or-later +// +package org.dogtagpki.server.ca.cli; + +import org.dogtagpki.cli.CLI; + +/** + * @author Marco Fargetta {@literal } + */ +public class CAIdGeneratorCLI extends CLI { + + public CAIdGeneratorCLI(CLI parent) { + super("generator", "CA id generator commands", parent); + + addModule(new CAIdGeneratorUpdateCLI(this)); + } + +} diff --git a/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CAIdGeneratorUpdateCLI.java b/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CAIdGeneratorUpdateCLI.java new file mode 100644 index 00000000000..3bea7671761 --- /dev/null +++ b/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CAIdGeneratorUpdateCLI.java @@ -0,0 +1,53 @@ +// +// Copyright Red Hat, Inc. +// +// SPDX-License-Identifier: GPL-2.0-or-later +// +package org.dogtagpki.server.ca.cli; + +import com.netscape.cmscore.apps.DatabaseConfig; +import com.netscape.cmscore.dbs.CertificateRepository; +import com.netscape.cmscore.dbs.Repository; +import com.netscape.cmscore.dbs.Repository.IDGenerator; +import com.netscape.cmscore.ldapconn.LdapAuthInfo; +import com.netscape.cmscore.ldapconn.LdapConnInfo; +import com.netscape.cmscore.ldapconn.PKISocketFactory; +import org.dogtagpki.cli.CLI; +import org.dogtagpki.server.cli.SubsystemIdGeneratorUpdateCLI; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Marco Fargetta {@literal } + */ +public class CAIdGeneratorUpdateCLI extends SubsystemIdGeneratorUpdateCLI { + private static final Logger logger = LoggerFactory.getLogger(CAIdGeneratorUpdateCLI.class); + + public CAIdGeneratorUpdateCLI(CLI parent) { + super(parent); + } + + @Override + protected void updateSerialNumberRangeGenerator(PKISocketFactory socketFactory, LdapConnInfo connInfo, + LdapAuthInfo authInfo, DatabaseConfig dbConfig, String baseDN, IDGenerator newGenerator, String hostName, String securePort) throws Exception { + String value = dbConfig.getString( + CertificateRepository.PROP_CERT_ID_GENERATOR, + CertificateRepository.DEFAULT_CERT_ID_GENERATOR); + idGenerator = IDGenerator.fromString(value); + + if (newGenerator == IDGenerator.RANDOM && idGenerator != IDGenerator.RANDOM) { + dbConfig.put(CertificateRepository.PROP_CERT_ID_GENERATOR, newGenerator.toString()); + dbConfig.put(CertificateRepository.PROP_CERT_ID_LENGTH, "128"); + dbConfig.remove("enableRandomSerialNumbers"); + dbConfig.remove("randomSerialNumberCounter"); + } + if (newGenerator == IDGenerator.LEGACY_2 && idGenerator == IDGenerator.LEGACY) { + dbConfig.put(CertificateRepository.PROP_CERT_ID_GENERATOR, newGenerator.toString()); + dbConfig.put(CertificateRepository.PROP_CERT_ID_RADIX, Integer.toString(Repository.HEX)); + } + + super.updateSerialNumberRangeGenerator(socketFactory, connInfo, authInfo, dbConfig, baseDN, newGenerator, hostName, securePort); + } + + +} diff --git a/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CARangeUpdateCLI.java b/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CARangeUpdateCLI.java index 5628173fbc0..1f10bd92fe3 100644 --- a/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CARangeUpdateCLI.java +++ b/base/ca/src/main/java/org/dogtagpki/server/ca/cli/CARangeUpdateCLI.java @@ -39,9 +39,9 @@ public void updateSerialNumberRange( String value = dbConfig.getString( CertificateRepository.PROP_CERT_ID_GENERATOR, CertificateRepository.DEFAULT_CERT_ID_GENERATOR); - IDGenerator idGenerator = IDGenerator.fromString(value); + idGenerator = IDGenerator.fromString(value); - if (idGenerator != IDGenerator.LEGACY) { + if (idGenerator == IDGenerator.RANDOM) { logger.info("No need to update certificate ID range"); return; } diff --git a/base/kra/src/main/java/com/netscape/cmscore/dbs/KeyRepository.java b/base/kra/src/main/java/com/netscape/cmscore/dbs/KeyRepository.java index dbc87cc0fc4..48d869025b7 100644 --- a/base/kra/src/main/java/com/netscape/cmscore/dbs/KeyRepository.java +++ b/base/kra/src/main/java/com/netscape/cmscore/dbs/KeyRepository.java @@ -45,6 +45,7 @@ public class KeyRepository extends Repository { public static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(KeyRepository.class); public static final String PROP_KEY_ID_GENERATOR = "key.id.generator"; + public static final String PROP_KEY_ID_RADIX = "key.id.radix"; public static final String DEFAULT_KEY_ID_GENERATOR = "legacy"; public static final String PROP_KEY_ID_LENGTH = "key.id.length"; @@ -62,7 +63,15 @@ public KeyRepository( SecureRandom secureRandom, DBSubsystem dbSubsystem) { - super(dbSubsystem, 16); + super(dbSubsystem, HEX); + DatabaseConfig dbc = dbSubsystem.getDBConfigStore(); + try { + this.mRadix = dbc.getInteger(PROP_KEY_ID_RADIX, HEX); + logger.debug("KeyRepository: number radix {}", this.mRadix); + + } catch (EBaseException ex) { + logger.debug("KeyRepository: error reading number radix config, using default {} for ", HEX); + } this.secureRandom = secureRandom; } @@ -85,7 +94,8 @@ public void init() throws Exception { idLength = dbConfig.getInteger(PROP_KEY_ID_LENGTH, DEFAULT_KEY_ID_LENGTH); logger.info("KeyRepository: - key ID length: {}", idLength); - + } else if (idGenerator == IDGenerator.LEGACY_2) { + initLegacy2Generator(); } else { initLegacyGenerator(); } @@ -168,6 +178,45 @@ public void init() throws Exception { } + protected void initLegacy2Generator() throws EBaseException { + DatabaseConfig dbConfig = dbSubsystem.getDBConfigStore(); + + rangeDN = dbConfig.getSerialRangeDN() + "," + dbSubsystem.getBaseDN(); + logger.debug("KeyRepository: - range DN: " + rangeDN); + + minSerialName = DatabaseConfig.MIN_SERIAL_NUMBER; + mMinSerialNo = dbConfig.getBigInteger(minSerialName, null); + logger.debug("KeyRepository: - min serial: " + mMinSerialNo); + + maxSerialName = DatabaseConfig.MAX_SERIAL_NUMBER; + mMaxSerialNo = dbConfig.getBigInteger(maxSerialName, null); + logger.debug("KeyRepository: - max serial: " + mMaxSerialNo); + + nextMinSerialName = DatabaseConfig.NEXT_MIN_SERIAL_NUMBER; + String nextMinSerial = dbConfig.getNextBeginSerialNumber(); + if (nextMinSerial == null || nextMinSerial.equals("-1")) { + mNextMinSerialNo = null; + } else { + mNextMinSerialNo = dbConfig.getBigInteger(DatabaseConfig.NEXT_MIN_SERIAL_NUMBER, null); + } + logger.debug("KeyRepository: - next min serial: " + mNextMinSerialNo); + + nextMaxSerialName = DatabaseConfig.NEXT_MAX_SERIAL_NUMBER; + String nextMaxSerial = dbConfig.getNextEndSerialNumber(); + if (nextMaxSerial == null || nextMaxSerial.equals("-1")) { + mNextMaxSerialNo = null; + } else { + mNextMaxSerialNo = dbConfig.getBigInteger(DatabaseConfig.NEXT_MAX_SERIAL_NUMBER, null); + } + logger.debug("KeyRepository: - next max serial: " + mNextMaxSerialNo); + + mLowWaterMarkNo = dbConfig.getBigInteger(DatabaseConfig.SERIAL_LOW_WATER_MARK, null); + logger.debug("KeyRepository: - low water mark serial: " + mNextMaxSerialNo); + + mIncrementNo = dbConfig.getBigInteger(DatabaseConfig.SERIAL_INCREMENT, null); + logger.debug("KeyRepository: - increment serial: " + mIncrementNo); + } + public void initLegacyGenerator() throws Exception { DatabaseConfig dbConfig = dbSubsystem.getDBConfigStore(); diff --git a/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRACLI.java b/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRACLI.java index 4861c02d4ec..08c2427866b 100644 --- a/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRACLI.java +++ b/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRACLI.java @@ -35,6 +35,7 @@ public KRACLI(CLI parent) { addModule(new SubsystemDBCLI(this)); addModule(new SubsystemGroupCLI(this)); addModule(new KRARangeCLI(this)); + addModule(new KRAIdCLI(this)); addModule(new SubsystemUserCLI(this)); addModule(new SDCLI(this)); } diff --git a/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRAIdCLI.java b/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRAIdCLI.java new file mode 100644 index 00000000000..1e8cd8ef601 --- /dev/null +++ b/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRAIdCLI.java @@ -0,0 +1,19 @@ +// +// Copyright Red Hat, Inc. +// +// SPDX-License-Identifier: GPL-2.0-or-later +// +package org.dogtagpki.server.kra.cli; + +import org.dogtagpki.cli.CLI; + +/** + * @author Marco Fargetta {@literal } + */ +public class KRAIdCLI extends CLI { + public KRAIdCLI(CLI parent) { + super("id", "CA id generator management commands", parent); + + addModule(new KRAIdGeneratorCLI(this)); + } +} diff --git a/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRAIdGeneratorCLI.java b/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRAIdGeneratorCLI.java new file mode 100644 index 00000000000..8ebd8385bd2 --- /dev/null +++ b/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRAIdGeneratorCLI.java @@ -0,0 +1,18 @@ +// +// Copyright Red Hat, Inc. +// +// SPDX-License-Identifier: GPL-2.0-or-later +// +package org.dogtagpki.server.kra.cli; + +import org.dogtagpki.cli.CLI; +/** + * @author Marco Fargetta {@literal } + */ +public class KRAIdGeneratorCLI extends CLI { + public KRAIdGeneratorCLI(CLI parent) { + super("generator", "kra range generator commands", parent); + + addModule(new kraIdGeneratorUpdateCLI(this)); + } +} diff --git a/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRARangeUpdateCLI.java b/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRARangeUpdateCLI.java index de387086285..d5b7ea09dd7 100644 --- a/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRARangeUpdateCLI.java +++ b/base/kra/src/main/java/org/dogtagpki/server/kra/cli/KRARangeUpdateCLI.java @@ -41,7 +41,7 @@ public void updateSerialNumberRange( KeyRepository.DEFAULT_KEY_ID_GENERATOR); IDGenerator idGenerator = IDGenerator.fromString(value); - if (idGenerator != IDGenerator.LEGACY) { + if (idGenerator == IDGenerator.RANDOM) { logger.info("No need to update key ID range"); return; } diff --git a/base/kra/src/main/java/org/dogtagpki/server/kra/cli/kraIdGeneratorUpdateCLI.java b/base/kra/src/main/java/org/dogtagpki/server/kra/cli/kraIdGeneratorUpdateCLI.java new file mode 100644 index 00000000000..bd5c5e72d78 --- /dev/null +++ b/base/kra/src/main/java/org/dogtagpki/server/kra/cli/kraIdGeneratorUpdateCLI.java @@ -0,0 +1,45 @@ +// +// Copyright Red Hat, Inc. +// +// SPDX-License-Identifier: GPL-2.0-or-later +// +package org.dogtagpki.server.kra.cli; + +import com.netscape.cmscore.apps.DatabaseConfig; +import com.netscape.cmscore.dbs.KeyRepository; +import com.netscape.cmscore.dbs.Repository; +import com.netscape.cmscore.ldapconn.LdapAuthInfo; +import com.netscape.cmscore.ldapconn.LdapConnInfo; +import com.netscape.cmscore.ldapconn.PKISocketFactory; +import org.dogtagpki.cli.CLI; +import org.dogtagpki.server.cli.SubsystemIdGeneratorUpdateCLI; + +/** + * @author Marco Fargetta {@literal } + */ +public class kraIdGeneratorUpdateCLI extends SubsystemIdGeneratorUpdateCLI { + + public kraIdGeneratorUpdateCLI(CLI parent) { + super(parent); + } + + @Override + protected void updateSerialNumberRangeGenerator(PKISocketFactory socketFactory, LdapConnInfo connInfo, + LdapAuthInfo authInfo, DatabaseConfig dbConfig, String baseDN, Repository.IDGenerator newGenerator, String hostName, String securePort) throws Exception { + String value = dbConfig.getString( + KeyRepository.PROP_KEY_ID_GENERATOR, + KeyRepository.DEFAULT_KEY_ID_GENERATOR); + idGenerator = Repository.IDGenerator.fromString(value); + + if (newGenerator == Repository.IDGenerator.RANDOM && idGenerator != Repository.IDGenerator.RANDOM) { + dbConfig.put(KeyRepository.PROP_KEY_ID_GENERATOR, newGenerator.toString()); + dbConfig.put(KeyRepository.PROP_KEY_ID_LENGTH, "128"); + } + if (newGenerator == Repository.IDGenerator.LEGACY_2 && idGenerator == Repository.IDGenerator.LEGACY) { + dbConfig.put(KeyRepository.PROP_KEY_ID_GENERATOR, newGenerator.toString()); + dbConfig.put(KeyRepository.PROP_KEY_ID_RADIX, Integer.toString(Repository.HEX)); + } + + super.updateSerialNumberRangeGenerator(socketFactory, connInfo, authInfo, dbConfig, baseDN, newGenerator, hostName, securePort); + } +} diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg index f73cb60fd69..745d1278792 100644 --- a/base/server/etc/default.cfg +++ b/base/server/etc/default.cfg @@ -364,13 +364,13 @@ pki_request_number_range_transfer= pki_replica_number_range_start= pki_replica_number_range_end= -# Cert cert ID generator: legacy, random +# Cert cert ID generator: legacy, legacy2, random pki_cert_id_generator=random # Cert cert ID length in bits pki_cert_id_length=128 -# Cert request ID generator: legacy, random +# Cert request ID generator: legacy, legacy2, random pki_request_id_generator=random # Cert request ID length in bits @@ -475,7 +475,7 @@ pki_key_id_generator=random # Key ID length in bits pki_key_id_length=128 -# Key request ID generator: legacy, random +# Key request ID generator: legacy, legacy2, random pki_request_id_generator=random # Key request ID length in bits diff --git a/base/server/python/pki/server/cli/ca.py b/base/server/python/pki/server/cli/ca.py index a96d3213abe..a8b4a9d892f 100644 --- a/base/server/python/pki/server/cli/ca.py +++ b/base/server/python/pki/server/cli/ca.py @@ -36,6 +36,7 @@ import pki.server.cli.config import pki.server.cli.db import pki.server.cli.group +import pki.server.cli.id import pki.server.cli.range import pki.server.cli.subsystem import pki.server.cli.user @@ -61,6 +62,7 @@ def __init__(self): self.add_module(pki.server.cli.group.GroupCLI(self)) self.add_module(CAProfileCLI()) self.add_module(pki.server.cli.range.RangeCLI(self)) + self.add_module(pki.server.cli.id.IdCLI(self)) self.add_module(pki.server.cli.user.UserCLI(self)) diff --git a/base/server/python/pki/server/cli/id.py b/base/server/python/pki/server/cli/id.py new file mode 100644 index 00000000000..05f7d0d555a --- /dev/null +++ b/base/server/python/pki/server/cli/id.py @@ -0,0 +1,187 @@ +# +# Copyright Red Hat, Inc. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +from __future__ import absolute_import +from __future__ import print_function +import getopt +import logging +import sys + +import pki.cli + +logger = logging.getLogger(__name__) + + +class IdCLI(pki.cli.CLI): + + def __init__(self, parent): + super().__init__( + 'id', + '%s id configuration management commands' % parent.name.upper()) + + self.parent = parent + self.add_module(IdGeneratorCLI(self)) + + +class IdGeneratorCLI(pki.cli.CLI): + + def __init__(self, parent): + super().__init__('generator', + '%s id generator configuration' % parent.parent.name.upper()) + + self.parent = parent + self.add_module(IdGeneratorShowCLI(self)) + self.add_module(IdGeneratorUpdateCLI(self)) + + +class IdGeneratorShowCLI(pki.cli.CLI): + + def __init__(self, parent): + super().__init__('show', 'Display %s id generator' % parent.parent.parent.name.upper()) + + self.parent = parent + + def print_help(self): + print('Usage: pki-server %s-id-generator-show [OPTIONS]' % + self.parent.parent.parent.name) + print() + print(' -i, --instance Instance ID (default: pki-tomcat).') + print(' -v, --verbose Run in verbose mode.') + print(' --debug Run in debug mode.') + print(' --help Show help message.') + print() + + def execute(self, argv): + try: + opts, _ = getopt.gnu_getopt(argv, 'i:v', [ + 'instance=', + 'verbose', 'debug', 'help']) + + except getopt.GetoptError as e: + logger.error(e) + self.print_help() + sys.exit(1) + + instance_name = 'pki-tomcat' + subsystem_name = self.parent.parent.parent.name + + for o, a in opts: + if o in ('-i', '--instance'): + instance_name = a + + elif o in ('-v', '--verbose'): + logging.getLogger().setLevel(logging.INFO) + + elif o == '--debug': + logging.getLogger().setLevel(logging.DEBUG) + + elif o == '--help': + self.print_help() + sys.exit() + + else: + logger.error('Invalid option: %s', o) + self.print_help() + sys.exit(1) + + instance = pki.server.PKIServerFactory.create(instance_name) + if not instance.exists(): + logger.error('Invalid instance: %s', instance_name) + sys.exit(1) + + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) + + if not subsystem: + logger.error('No %s subsystem in instance %s', + subsystem_name.upper(), instance_name) + sys.exit(1) + + print(' Request ID generator: %s' % subsystem.config.get('dbs.request.id.generator')) + print(' Cert ID generator: %s' % subsystem.config.get('dbs.cert.id.generator')) + + +class IdGeneratorUpdateCLI(pki.cli.CLI): + + def __init__(self, parent): + super().__init__('update', 'Update %s id generator' % parent.parent.parent.name.upper()) + + self.parent = parent + + def print_help(self): + print('Usage: pki-server %s-id-generator-update [OPTIONS] ' % + self.parent.parent.parent.name) + print() + print(' -t, --type Type for the generator (request or cert).') + print(' -i, --instance Instance ID (default: pki-tomcat).') + print(' -v, --verbose Run in verbose mode.') + print(' --debug Run in debug mode.') + print(' --help Show help message.') + print() + + def execute(self, argv): + try: + opts, args = getopt.gnu_getopt(argv, 'i:t:v', [ + 'instance=', 'type=', + 'verbose', 'debug', 'help']) + + except getopt.GetoptError as e: + logger.error(e) + self.print_help() + sys.exit(1) + + if len(args) != 1: + logger.error('Missing new generator') + self.print_help() + sys.exit(1) + + new_generator = args[0] + instance_name = 'pki-tomcat' + subsystem_name = self.parent.parent.parent.name + generator_type = None + + for o, a in opts: + if o in ('-t', '--type'): + generator_type = a + + elif o in ('-i', '--instance'): + instance_name = a + + elif o in ('-v', '--verbose'): + logging.getLogger().setLevel(logging.INFO) + + elif o == '--debug': + logging.getLogger().setLevel(logging.DEBUG) + + elif o == '--help': + self.print_help() + sys.exit() + + else: + logger.error('Invalid option: %s', o) + self.print_help() + sys.exit(1) + + if not generator_type: + logger.error('No specified') + self.print_help() + sys.exit(1) + + instance = pki.server.PKIServerFactory.create(instance_name) + if not instance.exists(): + logger.error('Invalid instance: %s', instance_name) + sys.exit(1) + + instance.load() + + subsystem = instance.get_subsystem(subsystem_name) + + if not subsystem: + logger.error('No %s subsystem in instance %s', + subsystem_name.upper(), instance_name) + sys.exit(1) + + subsystem.update_id_generator(new_generator, generator_type) diff --git a/base/server/python/pki/server/deployment/__init__.py b/base/server/python/pki/server/deployment/__init__.py index 2929ad4e4da..7ec81f72c20 100644 --- a/base/server/python/pki/server/deployment/__init__.py +++ b/base/server/python/pki/server/deployment/__init__.py @@ -1175,8 +1175,9 @@ def configure_ca(self, subsystem): request_id_generator = self.mdict['pki_request_id_generator'] + subsystem.set_config('dbs.request.id.generator', request_id_generator) + if request_id_generator == 'random': - subsystem.set_config('dbs.request.id.generator', request_id_generator) subsystem.set_config('dbs.request.id.length', self.mdict['pki_request_id_length']) else: # legacy @@ -1209,8 +1210,9 @@ def configure_ca(self, subsystem): cert_id_generator = self.mdict['pki_cert_id_generator'] + subsystem.set_config('dbs.cert.id.generator', cert_id_generator) + if cert_id_generator == 'random': - subsystem.set_config('dbs.cert.id.generator', cert_id_generator) subsystem.set_config('dbs.cert.id.length', self.mdict['pki_cert_id_length']) else: # legacy @@ -1264,8 +1266,9 @@ def configure_kra(self, subsystem): request_id_generator = self.mdict['pki_request_id_generator'] + subsystem.set_config('dbs.request.id.generator', request_id_generator) + if request_id_generator == 'random': - subsystem.set_config('dbs.request.id.generator', request_id_generator) subsystem.set_config('dbs.request.id.length', self.mdict['pki_request_id_length']) else: # legacy @@ -1278,8 +1281,9 @@ def configure_kra(self, subsystem): key_id_generator = self.mdict['pki_key_id_generator'] + subsystem.set_config('dbs.key.id.generator', key_id_generator) + if key_id_generator == 'random': - subsystem.set_config('dbs.key.id.generator', key_id_generator) subsystem.set_config('dbs.key.id.length', self.mdict['pki_key_id_length']) else: # legacy @@ -1862,7 +1866,7 @@ def is_using_legacy_id_generator(self, subsystem): request_id_generator = subsystem.config.get('dbs.request.id.generator', 'legacy') logger.info('Request ID generator: %s', request_id_generator) - if request_id_generator == 'legacy': + if request_id_generator != 'random': return True if subsystem.type == 'CA': @@ -1870,7 +1874,7 @@ def is_using_legacy_id_generator(self, subsystem): cert_id_generator = subsystem.config.get('dbs.cert.id.generator', 'legacy') logger.info('Certificate ID generator: %s', cert_id_generator) - if cert_id_generator == 'legacy': + if cert_id_generator != 'random': return True elif subsystem.type == 'KRA': @@ -1878,7 +1882,7 @@ def is_using_legacy_id_generator(self, subsystem): key_id_generator = subsystem.config.get('dbs.key.id.generator', 'legacy') logger.info('Key ID generator: %s', key_id_generator) - if key_id_generator == 'legacy': + if key_id_generator != 'random': return True return False @@ -2876,7 +2880,7 @@ def import_cert_request(self, subsystem, tag, request): request_id_generator = subsystem.config.get('dbs.request.id.generator', 'legacy') - if request_id_generator == 'legacy': + if request_id_generator != 'random': # call the server to generate legacy request ID logger.info('Creating request ID for %s cert', tag) request.systemCert.requestID = self.client.createRequestID(request) @@ -2895,7 +2899,7 @@ def import_cert_request(self, subsystem, tag, request): dns_names=request.systemCert.dnsNames, adjust_validity=request.systemCert.adjustValidity) - if request_id_generator != 'legacy': + if request_id_generator == 'random': # get the request ID generated by pki-server ca-cert-request-import request.systemCert.requestID = result['requestID'] logger.info('- request ID: %s', request.systemCert.requestID) @@ -3347,7 +3351,7 @@ def create_cert_id(self, subsystem, tag, request): cert_id_generator = subsystem.config.get('dbs.cert.id.generator', 'legacy') - if cert_id_generator == 'legacy': + if cert_id_generator != 'random': # call the server to generate legacy cert ID logger.info('Creating cert ID for %s cert', tag) cert_id = self.client.createCertID(request) diff --git a/base/server/python/pki/server/subsystem.py b/base/server/python/pki/server/subsystem.py index 9ca4516110f..8c5382d97f9 100644 --- a/base/server/python/pki/server/subsystem.py +++ b/base/server/python/pki/server/subsystem.py @@ -1515,7 +1515,7 @@ def request_ranges(self, master_url, session_id=None, install_token=None): # request cert/key request ID range if it uses legacy generator if self.type in ['CA', 'KRA'] and \ - self.config.get('dbs.request.id.generator', 'legacy') == 'legacy': + self.config.get('dbs.request.id.generator', 'legacy') != 'random': logger.info('Requesting request ID range') @@ -1527,9 +1527,9 @@ def request_ranges(self, master_url, session_id=None, install_token=None): # request cert/key ID range if it uses legacy generator if self.type == 'CA' and \ - self.config.get('dbs.cert.id.generator', 'legacy') == 'legacy' or \ + self.config.get('dbs.cert.id.generator', 'legacy') != 'random' or \ self.type == 'KRA' \ - and self.config.get('dbs.key.id.generator', 'legacy') == 'legacy': + and self.config.get('dbs.key.id.generator', 'legacy') != 'random': logger.info('Requesting serial number range') @@ -1563,6 +1563,22 @@ def update_ranges(self, as_current_user=False): self.run(cmd, as_current_user=as_current_user) + def update_id_generator(self, generator, generator_type, as_current_user=False): + + cmd = [self.name + '-id-generator-update'] + + if logger.isEnabledFor(logging.DEBUG): + cmd.append('--debug') + + elif logger.isEnabledFor(logging.INFO): + cmd.append('--verbose') + + cmd.append('--type') + cmd.append(generator_type) + cmd.append(generator) + + self.run(cmd, as_current_user=as_current_user) + def retrieve_config(self, master_url, names, substores, session_id=None, install_token=None): tmpdir = tempfile.mkdtemp() diff --git a/base/server/src/main/java/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java b/base/server/src/main/java/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java index 53bd6765516..881c5940f1f 100644 --- a/base/server/src/main/java/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java +++ b/base/server/src/main/java/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java @@ -124,25 +124,22 @@ protected void process(CMSRequest cmsReq) throws EBaseException { repo.checkRanges(); } - int radix = 10; + int radix = repo.getRadix(); String endNumConfig = null; String cloneNumConfig = null; String nextEndConfig = null; if (type.equals("request")) { - radix = 10; endNumConfig = "endRequestNumber"; cloneNumConfig = "requestCloneTransferNumber"; nextEndConfig = "nextEndRequestNumber"; } else if (type.equals("serialNo")) { - radix = 16; endNumConfig = "endSerialNumber"; cloneNumConfig = "serialCloneTransferNumber"; nextEndConfig = "nextEndSerialNumber"; } else if (type.equals("replicaId")) { - radix = 10; endNumConfig = "endReplicaNumber"; cloneNumConfig = "replicaCloneTransferNumber"; nextEndConfig = "nextEndReplicaNumber"; @@ -161,12 +158,19 @@ protected void process(CMSRequest cmsReq) throws EBaseException { * cases this is done by a scheduled task). */ - String endNumStr = dbConfig.getString(endNumConfig); - BigInteger endNum = new BigInteger(endNumStr, radix); + BigInteger endNum; + BigInteger transferSize; + if (repo.getIDGenerator() == Repository.IDGenerator.LEGACY_2) { + endNum = dbConfig.getBigInteger(endNumConfig); + transferSize = dbConfig.getBigInteger(cloneNumConfig); + } else { + String endNumStr = dbConfig.getString(endNumConfig); + endNum = new BigInteger(endNumStr, radix); + + String transferSizeStr = dbConfig.getString(cloneNumConfig, ""); + transferSize = new BigInteger(transferSizeStr, radix); + } logger.info("UpdateNumberRange: dbs." + endNumConfig + ": " + endNum); - - String transferSizeStr = dbConfig.getString(cloneNumConfig, ""); - BigInteger transferSize = new BigInteger(transferSizeStr, radix); logger.info("UpdateNumberRange: dbs." + cloneNumConfig + ": " + transferSize); // transferred range will start at beginNum @@ -224,7 +228,11 @@ protected void process(CMSRequest cmsReq) throws EBaseException { * this scenario is unlikely to arise. Furthermore, * recovery is automatic thanks to the scheduled tasks. */ - endNum = new BigInteger(dbConfig.getString(nextEndConfig, ""), radix); + if (repo.getIDGenerator() == Repository.IDGenerator.LEGACY_2) { + endNum = dbConfig.getBigInteger(nextEndConfig); + } else { + endNum = new BigInteger(dbConfig.getString(nextEndConfig, ""), radix); + } BigInteger newEndNum = endNum.subtract(transferSize); logger.info("UpdateNumberRange: Transferring from the end of next range"); @@ -232,7 +240,11 @@ protected void process(CMSRequest cmsReq) throws EBaseException { logger.info("UpdateNumberRange: Next range new end: " + newEndNum); repo.setNextMaxSerial(newEndNum); - dbConfig.putString(nextEndConfig, newEndNum.toString(radix)); + String strNewEndNum = newEndNum.toString(radix); + if (repo.getIDGenerator() == Repository.IDGenerator.LEGACY_2 && radix == Repository.HEX) { + strNewEndNum = "0x" + strNewEndNum; + } + dbConfig.putString(nextEndConfig, strNewEndNum); beginNum = newEndNum.add(BigInteger.ONE); } else { @@ -242,6 +254,9 @@ protected void process(CMSRequest cmsReq) throws EBaseException { BigInteger newEndNum = beginNum.subtract(BigInteger.ONE); repo.setMaxSerial(newEndNum); String newValStr = newEndNum.toString(radix); + if (repo.getIDGenerator() == Repository.IDGenerator.LEGACY_2 && radix == Repository.HEX) { + newValStr = "0x" + newValStr; + } dbConfig.putString(endNumConfig, newValStr); logger.info("UpdateNumberRange: New current range: " + nextSerial + ".." + newEndNum); @@ -273,8 +288,13 @@ protected void process(CMSRequest cmsReq) throws EBaseException { JSONObject jsonObj = new JSONObject(); ObjectNode responseNode = jsonObj.getMapper().createObjectNode(); responseNode.put("Status", SUCCESS); - responseNode.put("beginNumber", beginNum.toString(radix)); - responseNode.put("endNumber", endNum.toString(radix)); + if(repo.getIDGenerator() == Repository.IDGenerator.LEGACY_2 && radix == Repository.HEX) { + responseNode.put("beginNumber", "0x" + beginNum.toString(radix)); + responseNode.put("endNumber", "0x" + endNum.toString(radix)); + } else { + responseNode.put("beginNumber", beginNum.toString(radix)); + responseNode.put("endNumber", endNum.toString(radix)); + } jsonObj.getRootNode().set("Response", responseNode); outputResult(httpResp, "application/json", jsonObj.toByteArray()); cs.commit(false); diff --git a/base/server/src/main/java/com/netscape/cmscore/apps/DatabaseConfig.java b/base/server/src/main/java/com/netscape/cmscore/apps/DatabaseConfig.java index e895b3c11ba..186a4823ba0 100644 --- a/base/server/src/main/java/com/netscape/cmscore/apps/DatabaseConfig.java +++ b/base/server/src/main/java/com/netscape/cmscore/apps/DatabaseConfig.java @@ -37,6 +37,7 @@ public class DatabaseConfig extends ConfigStore { public static final String SERIAL_BASEDN = "serialDN"; public static final String SERIAL_RANGE_DN = "serialRangeDN"; + public static final String SERIAL_CLONE_TRANSFER_NUMBER = "serialCloneTransferNumber"; public static final String MIN_REQUEST_NUMBER = "beginRequestNumber"; public static final String MAX_REQUEST_NUMBER = "endRequestNumber"; @@ -49,6 +50,7 @@ public class DatabaseConfig extends ConfigStore { public static final String REQUEST_BASEDN = "requestDN"; public static final String REQUEST_RANGE_DN = "requestRangeDN"; + public static final String REQUEST_CLONE_TRANSFER_NUMBER = "requestCloneTransferNumber"; public static final String MIN_REPLICA_NUMBER = "beginReplicaNumber"; public static final String MAX_REPLICA_NUMBER = "endReplicaNumber"; @@ -124,6 +126,14 @@ public void setSerialRangeDN(String serialRangeDN) { putString(SERIAL_RANGE_DN, serialRangeDN); } + public String getSerialCloneTransferNumber() throws EBaseException { + return getString(SERIAL_CLONE_TRANSFER_NUMBER, ""); + } + + public void setSerialCloneTransferNumber(String serialCloneTransferNumber) { + putString(SERIAL_CLONE_TRANSFER_NUMBER, serialCloneTransferNumber); + } + public String getBeginSerialNumber() throws EBaseException { return getString(MIN_SERIAL_NUMBER, "0"); } @@ -188,6 +198,14 @@ public void setRequestRangeDN(String requestRangeDN) { putString(REQUEST_RANGE_DN, requestRangeDN); } + public String getRequestCloneTransferNumber() throws EBaseException { + return getString(REQUEST_CLONE_TRANSFER_NUMBER, ""); + } + + public void setRequestCloneTransferNumber(String requestCloneTransferNumber) { + putString(REQUEST_CLONE_TRANSFER_NUMBER, requestCloneTransferNumber); + } + public String getBeginRequestNumber() throws EBaseException { return getString(MIN_REQUEST_NUMBER, "0"); } diff --git a/base/server/src/main/java/com/netscape/cmscore/dbs/ReplicaIDRepository.java b/base/server/src/main/java/com/netscape/cmscore/dbs/ReplicaIDRepository.java index 089855003d4..c54123dd80b 100644 --- a/base/server/src/main/java/com/netscape/cmscore/dbs/ReplicaIDRepository.java +++ b/base/server/src/main/java/com/netscape/cmscore/dbs/ReplicaIDRepository.java @@ -38,7 +38,7 @@ public class ReplicaIDRepository extends Repository { * Constructs a certificate repository. */ public ReplicaIDRepository(DBSubsystem dbSubsystem) { - super(dbSubsystem, 10); + super(dbSubsystem, DEC); } @Override @@ -54,18 +54,10 @@ public void init() throws Exception { rangeDN = dbConfig.getReplicaRangeDN() + "," + dbSubsystem.getBaseDN(); logger.info("ReplicaIDRepository: - range DN: " + rangeDN); - minSerialName = DatabaseConfig.MIN_REPLICA_NUMBER; - String minSerial = dbConfig.getBeginReplicaNumber(); - if (minSerial != null) { - mMinSerialNo = new BigInteger(minSerial, mRadix); - } + mMinSerialNo = dbConfig.getBigInteger(DatabaseConfig.MIN_REPLICA_NUMBER, null); logger.info("ReplicaIDRepository: - min serial: " + mMinSerialNo); - maxSerialName = DatabaseConfig.MAX_REPLICA_NUMBER; - String maxSerial = dbConfig.getEndReplicaNumber(); - if (maxSerial != null) { - mMaxSerialNo = new BigInteger(maxSerial, mRadix); - } + mMaxSerialNo = dbConfig.getBigInteger(DatabaseConfig.MAX_REPLICA_NUMBER, null); logger.info("ReplicaIDRepository: - max serial: " + mMaxSerialNo); nextMinSerialName = DatabaseConfig.NEXT_MIN_REPLICA_NUMBER; @@ -73,7 +65,7 @@ public void init() throws Exception { if (nextMinSerial == null || nextMinSerial.equals("-1")) { mNextMinSerialNo = null; } else { - mNextMinSerialNo = new BigInteger(nextMinSerial, mRadix); + mNextMinSerialNo = dbConfig.getBigInteger(DatabaseConfig.NEXT_MIN_REPLICA_NUMBER, null); } logger.info("ReplicaIDRepository: - next min serial: " + mNextMinSerialNo); @@ -82,19 +74,15 @@ public void init() throws Exception { if (nextMaxSerial == null || nextMaxSerial.equals("-1")) { mNextMaxSerialNo = null; } else { - mNextMaxSerialNo = new BigInteger(nextMaxSerial, mRadix); + mNextMaxSerialNo = dbConfig.getBigInteger(DatabaseConfig.NEXT_MAX_REPLICA_NUMBER, null); } logger.info("ReplicaIDRepository: - next max serial: " + mNextMaxSerialNo); - String lowWaterMark = dbConfig.getReplicaLowWaterMark(); - if (lowWaterMark != null) { - mLowWaterMarkNo = new BigInteger(lowWaterMark, mRadix); - } + mLowWaterMarkNo = dbConfig.getBigInteger(DatabaseConfig.REPLICA_LOW_WATER_MARK, null); + logger.debug("ReplicaIDRepository: - low water mark serial: " + mNextMaxSerialNo); - String incrementNo = dbConfig.getReplicaIncrement(); - if (incrementNo != null) { - mIncrementNo = new BigInteger(incrementNo, mRadix); - } + mIncrementNo = dbConfig.getBigInteger(DatabaseConfig.REPLICA_INCREMENT, null); + logger.debug("ReplicaIDRepository: - increment serial: " + mIncrementNo); } /** diff --git a/base/server/src/main/java/com/netscape/cmscore/dbs/Repository.java b/base/server/src/main/java/com/netscape/cmscore/dbs/Repository.java index 90b905b6dce..ea2324810c2 100644 --- a/base/server/src/main/java/com/netscape/cmscore/dbs/Repository.java +++ b/base/server/src/main/java/com/netscape/cmscore/dbs/Repository.java @@ -50,7 +50,11 @@ public abstract class Repository { public static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(Repository.class); + public static final int HEX = 16; + public static final int DEC = 10; + public enum IDGenerator { + LEGACY_2("legacy2"), LEGACY("legacy"), RANDOM("random"); @@ -428,6 +432,9 @@ public void setMinSerialConfig() throws EBaseException { DatabaseConfig dbConfig = dbSubsystem.getDBConfigStore(); String serial = mMinSerialNo.toString(mRadix); + if (mRadix == HEX && idGenerator == IDGenerator.LEGACY_2) { + serial = "0x" + serial; + } logger.debug("Repository: Setting min serial number: " + serial); dbConfig.putString(minSerialName, serial); @@ -445,6 +452,9 @@ public void setMaxSerialConfig() throws EBaseException { DatabaseConfig dbConfig = dbSubsystem.getDBConfigStore(); String serial = mMaxSerialNo.toString(mRadix); + if (mRadix == HEX && idGenerator == IDGenerator.LEGACY_2) { + serial = "0x" + serial; + } logger.debug("Repository: Setting max serial number: " + serial); dbConfig.putString(maxSerialName, serial); @@ -466,6 +476,9 @@ public void setNextMinSerialConfig() throws EBaseException { dbConfig.remove(nextMinSerialName); } else { String serial = mNextMinSerialNo.toString(mRadix); + if (mRadix == HEX && idGenerator == IDGenerator.LEGACY_2) { + serial = "0x" + serial; + } logger.debug("Repository: Setting next min number: " + serial); dbConfig.putString(nextMinSerialName, serial); } @@ -488,6 +501,9 @@ public void setNextMaxSerialConfig() throws EBaseException { dbConfig.remove(nextMaxSerialName); } else { String serial = mNextMaxSerialNo.toString(mRadix); + if (mRadix == HEX && idGenerator == IDGenerator.LEGACY_2) { + serial = "0x" + serial; + } logger.debug("Repository: Setting next max number: " + serial); dbConfig.putString(nextMaxSerialName, serial); } @@ -622,9 +638,11 @@ public boolean hasRangeConflict() throws EBaseException { logger.info("Repository: Searching for conflicting entries"); + String minSerial = idGenerator == IDGenerator.LEGACY_2 ? + mMinSerialNo.toString() : mMinSerialNo.toString(mRadix); String filter = "(&(nsds5ReplConflict=*)(objectClass=pkiRange)(host= " + cs.getHostname() + ")(SecurePort=" + engine.getEESSLPort() + - ")(beginRange=" + mMinSerialNo.toString(mRadix) + "))"; + ")(beginRange=" + minSerial + "))"; LDAPSearchResults results = conn.search(rangeDN, LDAPv3.SCOPE_SUB, filter, null, false); @@ -697,8 +715,13 @@ public void checkRanges() throws EBaseException { logger.debug("Repository: Requesting next range"); String nextRange = getNextRange(); logger.debug("Repository: next range: " + nextRange); - - mNextMinSerialNo = new BigInteger(nextRange, mRadix); + if (idGenerator == IDGenerator.LEGACY_2) { + mNextMinSerialNo = new BigInteger(nextRange); + } else { + // nextRange is read as decimal in other places and with radix (hex default) here making + // its value inconsistent + mNextMinSerialNo = new BigInteger(nextRange, mRadix); + } if (mNextMinSerialNo == null) { logger.debug("Repository: Next range not available"); } else { diff --git a/base/server/src/main/java/com/netscape/cmscore/request/RequestRepository.java b/base/server/src/main/java/com/netscape/cmscore/request/RequestRepository.java index 0773d60de31..31aad37bfba 100644 --- a/base/server/src/main/java/com/netscape/cmscore/request/RequestRepository.java +++ b/base/server/src/main/java/com/netscape/cmscore/request/RequestRepository.java @@ -58,6 +58,7 @@ public class RequestRepository extends Repository { public static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(RequestRepository.class); public static final String PROP_REQUEST_ID_GENERATOR = "request.id.generator"; + public static final String PROP_REQUEST_ID_RADIX = "request.id.radix"; public static final String DEFAULT_REQUEST_ID_GENERATOR = "legacy"; public static final String PROP_REQUEST_ID_LENGTH = "request.id.length"; @@ -77,8 +78,15 @@ public RequestRepository( DBSubsystem dbSubsystem, String filter) { - super(dbSubsystem, 10); - + super(dbSubsystem, DEC); + DatabaseConfig dbc = dbSubsystem.getDBConfigStore(); + try { + this.mRadix = dbc.getInteger(PROP_REQUEST_ID_RADIX, DEC); + logger.debug("CertificateRepository: number radix {}", this.mRadix); + + } catch (EBaseException ex) { + logger.debug("CertificateRepository: error reading number radix config, using default {} for ", HEX); + } this.secureRandom = secureRandom; this.filter = filter; } @@ -102,7 +110,8 @@ public void init() throws Exception { idLength = dbConfig.getInteger(PROP_REQUEST_ID_LENGTH, DEFAULT_REQUEST_ID_LENGTH); logger.debug("RequestRepository: - request ID length: " + idLength); - + } else if (idGenerator == IDGenerator.LEGACY_2) { + initLegacy2Generator(); } else { initLegacyGenerator(); } @@ -112,6 +121,45 @@ public void init() throws Exception { RequestRecord.register(dbSubsystem); } + protected void initLegacy2Generator() throws EBaseException { + DatabaseConfig dbConfig = dbSubsystem.getDBConfigStore(); + + rangeDN = dbConfig.getRequestRangeDN() + "," + dbSubsystem.getBaseDN(); + logger.debug("RequestRepository: - range DN: " + rangeDN); + + minSerialName = DatabaseConfig.MIN_REQUEST_NUMBER; + mMinSerialNo = dbConfig.getBigInteger(minSerialName, null); + logger.debug("RequestRepository: - min serial: " + mMinSerialNo); + + maxSerialName = DatabaseConfig.MAX_REQUEST_NUMBER; + mMaxSerialNo = dbConfig.getBigInteger(maxSerialName, null); + logger.debug("RequestRepository: - max serial: " + mMaxSerialNo); + + nextMinSerialName = DatabaseConfig.NEXT_MIN_REQUEST_NUMBER; + String nextMinSerial = dbConfig.getNextBeginSerialNumber(); + if (nextMinSerial == null || nextMinSerial.equals("-1")) { + mNextMinSerialNo = null; + } else { + mNextMinSerialNo = dbConfig.getBigInteger(DatabaseConfig.NEXT_MIN_REQUEST_NUMBER, null); + } + logger.debug("RequestRepository: - next min serial: " + mNextMinSerialNo); + + nextMaxSerialName = DatabaseConfig.NEXT_MAX_REQUEST_NUMBER; + String nextMaxSerial = dbConfig.getNextEndSerialNumber(); + if (nextMaxSerial == null || nextMaxSerial.equals("-1")) { + mNextMaxSerialNo = null; + } else { + mNextMaxSerialNo = dbConfig.getBigInteger(DatabaseConfig.NEXT_MAX_REQUEST_NUMBER, null); + } + logger.debug("RequestRepository: - next max serial: " + mNextMaxSerialNo); + + mLowWaterMarkNo = dbConfig.getBigInteger(DatabaseConfig.REQUEST_LOW_WATER_MARK, null); + logger.debug("RequestRepository: - low water mark serial: " + mNextMaxSerialNo); + + mIncrementNo = dbConfig.getBigInteger(DatabaseConfig.REQUEST_INCREMENT, null); + logger.debug("RequestRepository: - increment serial: " + mIncrementNo); + } + public void initLegacyGenerator() throws Exception { DatabaseConfig dbConfig = dbSubsystem.getDBConfigStore(); diff --git a/base/server/src/main/java/org/dogtagpki/server/cli/SubsystemCLI.java b/base/server/src/main/java/org/dogtagpki/server/cli/SubsystemCLI.java index 2a11b4f0a71..93c9c17bcf9 100644 --- a/base/server/src/main/java/org/dogtagpki/server/cli/SubsystemCLI.java +++ b/base/server/src/main/java/org/dogtagpki/server/cli/SubsystemCLI.java @@ -16,6 +16,7 @@ import com.netscape.certsrv.base.EBaseException; import com.netscape.cmscore.apps.CMS; import com.netscape.cmscore.apps.EngineConfig; +import com.netscape.cmscore.apps.ServerConfig; import com.netscape.cmscore.base.ConfigStorage; import com.netscape.cmscore.base.FileConfigStorage; import com.netscape.cmscore.ldapconn.LDAPAuthenticationConfig; @@ -30,6 +31,7 @@ public abstract class SubsystemCLI extends CommandCLI { public static final Logger logger = LoggerFactory.getLogger(SubsystemCLI.class); + private static final String SERVER_XML = "server.xml"; protected SubsystemCLI(String name, String description, CLI parent) { super(name, description, parent); @@ -64,4 +66,18 @@ protected LdapAuthInfo getAuthInfo(PasswordStore passwordStore, LdapConnInfo con connInfo.getSecure()); return authInfo; } + + protected String getSecurePort(EngineConfig config) throws Exception { + + String path = CMS.getInstanceDir() + File.separator + "conf" + File.separator + SERVER_XML; + + ServerConfig serverConfig = ServerConfig.load(path); + String securePort = serverConfig.getSecurePort(); + + String port = config.getString("proxy.securePort", ""); + if (!port.equals("")) { + securePort = port; + } + return securePort; + } } diff --git a/base/server/src/main/java/org/dogtagpki/server/cli/SubsystemIdGeneratorUpdateCLI.java b/base/server/src/main/java/org/dogtagpki/server/cli/SubsystemIdGeneratorUpdateCLI.java new file mode 100644 index 00000000000..fc59c53561e --- /dev/null +++ b/base/server/src/main/java/org/dogtagpki/server/cli/SubsystemIdGeneratorUpdateCLI.java @@ -0,0 +1,310 @@ +// +// Copyright Red Hat, Inc. +// +// SPDX-License-Identifier: GPL-2.0-or-later +// +package org.dogtagpki.server.cli; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.cmscore.apps.CMS; +import com.netscape.cmscore.apps.DatabaseConfig; +import com.netscape.cmscore.apps.EngineConfig; +import com.netscape.cmscore.dbs.DBSubsystem; +import com.netscape.cmscore.dbs.Repository; +import com.netscape.cmscore.dbs.Repository.IDGenerator; +import static com.netscape.cmscore.dbs.Repository.logger; +import com.netscape.cmscore.ldapconn.LDAPConfig; +import com.netscape.cmscore.ldapconn.LDAPConnectionConfig; +import com.netscape.cmscore.ldapconn.LdapAuthInfo; +import com.netscape.cmscore.ldapconn.LdapBoundConnection; +import com.netscape.cmscore.ldapconn.LdapConnInfo; +import com.netscape.cmscore.ldapconn.PKISocketConfig; +import com.netscape.cmscore.ldapconn.PKISocketFactory; +import com.netscape.cmscore.request.RequestRepository; +import com.netscape.cmsutil.password.PasswordStore; +import com.netscape.cmsutil.password.PasswordStoreConfig; +import java.math.BigInteger; +import netscape.ldap.LDAPAttribute; +import netscape.ldap.LDAPAttributeSet; +import netscape.ldap.LDAPEntry; +import netscape.ldap.LDAPException; +import netscape.ldap.LDAPModification; +import netscape.ldap.LDAPSearchResults; +import netscape.ldap.LDAPv3; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Option; +import org.dogtagpki.cli.CLI; +import org.dogtagpki.util.logging.PKILogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Marco Fargetta {@literal } + */ +public abstract class SubsystemIdGeneratorUpdateCLI extends SubsystemCLI { + private static final Logger logger = LoggerFactory.getLogger(SubsystemIdGeneratorUpdateCLI.class); + protected IDGenerator idGenerator; + + public SubsystemIdGeneratorUpdateCLI(CLI parent) { + super("update", "Update " + parent.getParent().getParent().getName().toUpperCase() + " range generator", parent); + } + @Override + public void createOptions() { + options.addOption("t", "type", true, "Generator type to update."); + } + + @Override + public void execute(CommandLine cmd) throws Exception { + + if (!cmd.hasOption("type")) { + throw new Exception("Missing generator type."); + } + String generatorType = cmd.getOptionValue("type"); + + if (cmd.hasOption("debug")) { + PKILogger.setLevel(PKILogger.LogLevel.DEBUG); + + } else if (cmd.hasOption("verbose")) { + PKILogger.setLevel(PKILogger.LogLevel.INFO); + } + + String[] cmdArgs = cmd.getArgs(); + + if (cmdArgs.length != 1) { + throw new Exception("Missing generator"); + } + IDGenerator generator = IDGenerator.fromString(cmdArgs[0]); + + initializeTomcatJSS(); + String subsystem = parent.getParent().getParent().getName(); + EngineConfig cs = getEngineConfig(subsystem); + cs.load(); + + LDAPConfig ldapConfig = cs.getInternalDBConfig(); + String baseDN = ldapConfig.getBaseDN(); + + PasswordStoreConfig psc = cs.getPasswordStoreConfig(); + PasswordStore passwordStore = CMS.createPasswordStore(psc); + + LDAPConnectionConfig connConfig = ldapConfig.getConnectionConfig(); + + LdapConnInfo connInfo = new LdapConnInfo(connConfig); + LdapAuthInfo authInfo = getAuthInfo(passwordStore, connInfo, ldapConfig); + + PKISocketConfig socketConfig = cs.getSocketConfig(); + + PKISocketFactory socketFactory = new PKISocketFactory(); + socketFactory.setSecure(connInfo.getSecure()); + if (authInfo.getAuthType() == LdapAuthInfo.LDAP_AUTHTYPE_SSLCLIENTAUTH) { + socketFactory.setClientCertNickname(authInfo.getClientCertNickname()); + } + socketFactory.init(socketConfig); + + DatabaseConfig dbConfig = cs.getDatabaseConfig(); + + if (generatorType.equals("cert")){ + updateSerialNumberRangeGenerator( + socketFactory, + connInfo, + authInfo, + dbConfig, + baseDN, + generator, + cs.getHostname(), + getSecurePort(cs)); + cs.commit(false); + } else if (generatorType.equals("request")) { + updateRequestNumberRangeGenerator( + socketFactory, + connInfo, + authInfo, + dbConfig, + baseDN, + generator); + cs.commit(false); + } else { + throw new EBaseException("Generator type " + generatorType + " not supported."); + } + } + + protected void updateSerialNumberRangeGenerator(PKISocketFactory socketFactory, LdapConnInfo connInfo, + LdapAuthInfo authInfo, DatabaseConfig dbConfig, String baseDN, IDGenerator newGenerator, + String hostName, String securePort) throws Exception { + + if (newGenerator == IDGenerator.RANDOM && idGenerator != IDGenerator.RANDOM) { + logger.debug("Remove serial ranges from configuration"); + dbConfig.remove(DatabaseConfig.MIN_SERIAL_NUMBER); + dbConfig.remove(DatabaseConfig.MAX_SERIAL_NUMBER); + dbConfig.remove(DatabaseConfig.SERIAL_INCREMENT); + dbConfig.remove(DatabaseConfig.SERIAL_LOW_WATER_MARK); + dbConfig.remove(DatabaseConfig.SERIAL_CLONE_TRANSFER_NUMBER); + dbConfig.remove(DatabaseConfig.SERIAL_RANGE_DN); + return; + } + if (newGenerator == IDGenerator.LEGACY_2 && idGenerator == IDGenerator.LEGACY) { + logger.debug("Repository: Updating ranges entry to hex format"); + + LdapBoundConnection conn = new LdapBoundConnection(socketFactory, connInfo, authInfo); + try{ + String rangeDN = dbConfig.getSerialRangeDN() + "," + baseDN; + + String beginSerialNumber = dbConfig.getBeginSerialNumber(); + dbConfig.setBeginSerialNumber("0x" + beginSerialNumber); + + String endSerialNumber = dbConfig.getEndSerialNumber(); + try { + LDAPEntry entrySerial = conn.read("cn=" + beginSerialNumber+"," + rangeDN); + LDAPAttribute attrEnd = entrySerial.getAttribute("endRange"); + if (attrEnd != null) { + endSerialNumber = attrEnd.getStringValues().nextElement(); + } + } catch (LDAPException ldae) { + if (ldae.getLDAPResultCode() == 32) { + logger.debug("No range available, using config vaules"); + } else { + logger.error("LDAP error", ldae); + return; + } + + } + dbConfig.setEndSerialNumber("0x" + endSerialNumber); + + String serialIncrement = dbConfig.getSerialIncrement(); + dbConfig.setSerialIncrement("0x" + serialIncrement); + + String serialLowWaterMark = dbConfig.getSerialLowWaterMark(); + dbConfig.setSerialLowWaterMark("0x" + serialLowWaterMark); + + String serialCloneTransfer = dbConfig.getSerialCloneTransferNumber(); + dbConfig.setSerialCloneTransferNumber("0x" + serialCloneTransfer); + + String nextBeginSerial = dbConfig.getNextBeginSerialNumber(); + String nextEndSerial = dbConfig.getNextEndSerialNumber(); + if (nextBeginSerial != null && !nextBeginSerial.equals("-1")) { + dbConfig.setNextBeginSerialNumber("0x" + nextBeginSerial); + + try { + LDAPEntry entryNextSerial = conn.read("cn=" + nextBeginSerial + "," + rangeDN); + LDAPAttribute attrNextEnd = entryNextSerial.getAttribute("endRange"); + if (attrNextEnd != null) { + nextEndSerial = attrNextEnd.getStringValues().nextElement(); + } + } catch (LDAPException ldae) { + if (ldae.getLDAPResultCode() == 32) { + logger.debug("No range available, using config vaules"); + } else { + logger.error("LDAP error", ldae); + return; + } + + } + dbConfig.setNextEndSerialNumber("0x" + nextEndSerial); + endSerialNumber = nextEndSerial; + } + updateRanges(dbConfig, conn, baseDN, rangeDN, endSerialNumber, hostName, securePort); + } finally { + conn.disconnect(); + } + return; + } + throw new EBaseException("Update to " + newGenerator + " not supported"); + } + + protected void updateRequestNumberRangeGenerator(PKISocketFactory socketFactory, LdapConnInfo connInfo, + LdapAuthInfo authInfo, DatabaseConfig dbConfig, String baseDN, IDGenerator newGenerator) throws EBaseException { + + String value = dbConfig.getString( + RequestRepository.PROP_REQUEST_ID_GENERATOR, + RequestRepository.DEFAULT_REQUEST_ID_GENERATOR); + idGenerator = IDGenerator.fromString(value); + + if (newGenerator == IDGenerator.RANDOM && idGenerator != IDGenerator.RANDOM) { + logger.debug("Remove request ranges from configuration"); + dbConfig.remove(DatabaseConfig.MIN_REQUEST_NUMBER); + dbConfig.remove(DatabaseConfig.MAX_REQUEST_NUMBER); + dbConfig.remove(DatabaseConfig.REQUEST_INCREMENT); + dbConfig.remove(DatabaseConfig.REQUEST_LOW_WATER_MARK); + dbConfig.remove(DatabaseConfig.REQUEST_CLONE_TRANSFER_NUMBER); + dbConfig.remove(DatabaseConfig.REQUEST_RANGE_DN); + dbConfig.put(RequestRepository.PROP_REQUEST_ID_GENERATOR, newGenerator.toString()); + dbConfig.put(RequestRepository.PROP_REQUEST_ID_LENGTH, "128"); + return; + } + if (newGenerator == IDGenerator.LEGACY_2 && idGenerator == IDGenerator.LEGACY) { + dbConfig.put(RequestRepository.PROP_REQUEST_ID_GENERATOR, newGenerator.toString()); + dbConfig.put(RequestRepository.PROP_REQUEST_ID_RADIX, Integer.toString(Repository.DEC)); + return; + } + throw new EBaseException("Update to " + newGenerator + " not supported"); + } + + private void updateRanges(DatabaseConfig dbConfig, LdapBoundConnection conn, String baseDN, String rangeDN, String configEndSerialNumber, + String hostName, String securePort) throws Exception{ + + LDAPSearchResults ranges = conn.search(rangeDN, LDAPv3.SCOPE_SUB, "(objectClass=pkiRange)", null, false); + + BigInteger lastUsedSerial = BigInteger.ZERO; + boolean nextRangeToUpdate = true; + // Search for the last range entry. If it is associated to the CA to update or ranges are not defined + // then the nextRange is + while (ranges.hasMoreElements()) { + LDAPEntry entry = ranges.next(); + String endRange = entry.getAttribute("endRange").getStringValues().nextElement(); + String host = entry.getAttribute("host").getStringValues().nextElement(); + String port = entry.getAttribute("securePort").getStringValues().nextElement(); + BigInteger next = new BigInteger(endRange, 16); + if (lastUsedSerial.compareTo(next) < 0) { + lastUsedSerial = next; + nextRangeToUpdate = host.equals(hostName) && port.equals(securePort); + + } + } + + if (nextRangeToUpdate) { + // nextRange is updated using last range entry or, if no ranges, the configured endSerialNumber + if (lastUsedSerial == BigInteger.ZERO) { + lastUsedSerial = new BigInteger(configEndSerialNumber, 16); + } + BigInteger nextSerialNumber = lastUsedSerial.add(BigInteger.ONE); + String serialDN = dbConfig.getSerialDN() + "," + baseDN; + // store nextRange as decimal + LDAPAttribute attrSerialNextRange = new LDAPAttribute("nextRange", nextSerialNumber.toString()); + + LDAPModification serialmod = new LDAPModification(LDAPModification.REPLACE, attrSerialNextRange); + + conn.modify(serialDN, serialmod); + } + + LDAPSearchResults instanceRanges = conn.search(rangeDN, LDAPv3.SCOPE_SUB, "(&(objectClass=pkiRange)(host= " + + hostName + ")(SecurePort=" + securePort + "))", null, false); + + // update all ranges associated to the CA to update to decimal + while (instanceRanges.hasMoreElements()) { + LDAPEntry entry = instanceRanges.next(); + String beginRange = entry.getAttribute("beginRange").getStringValues().nextElement(); + BigInteger beginRangeNo = new BigInteger(beginRange, 16); + String endRange = entry.getAttribute("endRange").getStringValues().nextElement(); + BigInteger endRangeNo = new BigInteger(endRange, 16); + LDAPAttributeSet attrs = new LDAPAttributeSet(); + attrs.add(new LDAPAttribute("objectClass", "top")); + attrs.add(new LDAPAttribute("objectClass", "pkiRange")); + + // store beginRange as decimal + attrs.add(new LDAPAttribute("beginRange", beginRangeNo.toString())); + + // store endRange as decimal + attrs.add(new LDAPAttribute("endRange", endRangeNo.toString())); + + attrs.add(new LDAPAttribute("cn", beginRangeNo.toString())); + attrs.add(new LDAPAttribute("host", hostName)); + attrs.add(new LDAPAttribute("securePort", securePort)); + + String dn = "cn=" + beginRangeNo.toString() + "," + rangeDN; + LDAPEntry rangeEntry = new LDAPEntry(dn, attrs); + logger.info("SubsystemRangeGeneratorUpdateCLI.updateRanges: Remove entry " + entry.getDN()); + conn.delete(entry.getDN()); + logger.info("SubsystemRangeGeneratorUpdateCLI.updateRanges: Adding entry " + dn); + conn.add(rangeEntry); + } + } +} \ No newline at end of file diff --git a/base/server/src/main/java/org/dogtagpki/server/cli/SubsystemRangeUpdateCLI.java b/base/server/src/main/java/org/dogtagpki/server/cli/SubsystemRangeUpdateCLI.java index 90ce9ca8ab9..3578dabeeed 100644 --- a/base/server/src/main/java/org/dogtagpki/server/cli/SubsystemRangeUpdateCLI.java +++ b/base/server/src/main/java/org/dogtagpki/server/cli/SubsystemRangeUpdateCLI.java @@ -38,6 +38,8 @@ public class SubsystemRangeUpdateCLI extends SubsystemCLI { public static final Logger logger = LoggerFactory.getLogger(SubsystemRangeUpdateCLI.class); + protected IDGenerator idGenerator; + public SubsystemRangeUpdateCLI(CLI parent) { super("update", "Update " + parent.getParent().getName().toUpperCase() + " ranges", parent); } @@ -109,17 +111,20 @@ public void updateSerialNumberRange( LdapBoundConnection conn = new LdapBoundConnection(socketFactory, connInfo, authInfo); try { - // parse the end of current cert range as decimal - // NOTE: this is a bug, cert range is stored as hex in CS.cfg - BigInteger endSerialNumber = new BigInteger(dbConfig.getEndSerialNumber()); - - // generate nextRange in decimal - String nextSerialNumber = endSerialNumber.add(BigInteger.ONE).toString(); + BigInteger endSerialNumber; + if (idGenerator == IDGenerator.LEGACY_2) { + endSerialNumber = dbConfig.getBigInteger(DatabaseConfig.MAX_SERIAL_NUMBER); + } else { + // parse the end of current cert range as decimal + // NOTE: this is a bug, cert range is stored as hex in CS.cfg + endSerialNumber = new BigInteger(dbConfig.getEndSerialNumber()); + } + BigInteger nextSerialNumber = endSerialNumber.add(BigInteger.ONE); String serialDN = dbConfig.getSerialDN() + "," + baseDN; // store nextRange as decimal - LDAPAttribute attrSerialNextRange = new LDAPAttribute("nextRange", nextSerialNumber); + LDAPAttribute attrSerialNextRange = new LDAPAttribute("nextRange", nextSerialNumber.toString()); LDAPModification serialmod = new LDAPModification(LDAPModification.REPLACE, attrSerialNextRange); @@ -140,9 +145,9 @@ public void updateRequestNumberRange( String value = dbConfig.getString( RequestRepository.PROP_REQUEST_ID_GENERATOR, RequestRepository.DEFAULT_REQUEST_ID_GENERATOR); - IDGenerator idGenerator = IDGenerator.fromString(value); + idGenerator = IDGenerator.fromString(value); - if (idGenerator != IDGenerator.LEGACY) { + if (idGenerator == IDGenerator.RANDOM) { logger.info("No need to update request ID range"); return; } @@ -152,16 +157,19 @@ public void updateRequestNumberRange( try { logger.info("Updating request ID range"); - // parse the end of current range as decimal - BigInteger endRequestNumber = new BigInteger(dbConfig.getEndRequestNumber()); - - // generate nextRange in decimal - String nextRequestNumber = endRequestNumber.add(BigInteger.ONE).toString(); + BigInteger endRequestNumber; + if (idGenerator == IDGenerator.LEGACY_2) { + endRequestNumber = dbConfig.getBigInteger(DatabaseConfig.MAX_REQUEST_NUMBER); + } else { + // parse the end of current range as decimal + endRequestNumber = new BigInteger(dbConfig.getEndRequestNumber()); + } + BigInteger nextRequestNumber = endRequestNumber.add(BigInteger.ONE); String requestDN = dbConfig.getRequestDN() + "," + baseDN; // store nextRange as decimal - LDAPAttribute attrRequestNextRange = new LDAPAttribute("nextRange", nextRequestNumber); + LDAPAttribute attrRequestNextRange = new LDAPAttribute("nextRange", nextRequestNumber.toString()); LDAPModification requestmod = new LDAPModification(LDAPModification.REPLACE, attrRequestNextRange); diff --git a/base/server/src/test/java/com/netscape/cmscore/test/CMSBaseTestHelper.java b/base/server/src/test/java/com/netscape/cmscore/test/CMSBaseTestHelper.java index cdfdb58dc18..5e7817e8ac7 100644 --- a/base/server/src/test/java/com/netscape/cmscore/test/CMSBaseTestHelper.java +++ b/base/server/src/test/java/com/netscape/cmscore/test/CMSBaseTestHelper.java @@ -4,6 +4,7 @@ import org.mozilla.jss.netscape.security.x509.X509CertImpl; +import com.netscape.cmscore.apps.DatabaseConfig; import com.netscape.cmscore.dbs.DBRegistry; import com.netscape.cmscore.dbs.DBSSession; import com.netscape.cmscore.dbs.DBSubsystem; @@ -28,11 +29,13 @@ public static void setDbSubsystem(DBSubsystemStub dbSubsystem) { private static DBSubsystemStub dbSubsystem; static DBRegistry registry; static DBSSession session; + static DatabaseConfig databaseConfig; public static final void setUp() { setDbSubsystem(new DBSubsystemStub()); registry = new DBRegistry(); session = new DBSSession(); + databaseConfig = new DatabaseConfig(null); } public static X509CertImpl getFakeCert() throws CertificateException { @@ -72,5 +75,10 @@ public DBSSession createSession() { public DBRegistry getRegistry() { return registry; } + + @Override + public DatabaseConfig getDBConfigStore() { + return databaseConfig; + } } } From 9312f618aa3169735595616d3b658f6f7c933cd8 Mon Sep 17 00:00:00 2001 From: Marco Fargetta Date: Tue, 22 Oct 2024 10:36:10 +0200 Subject: [PATCH 2/2] Add legacy2 generator test to sequential tests --- .../workflows/ca-clone-sequential-test.yml | 531 ++++++++++++++++++ .github/workflows/ca-sequential-test.yml | 357 ++++++++++++ 2 files changed, 888 insertions(+) diff --git a/.github/workflows/ca-clone-sequential-test.yml b/.github/workflows/ca-clone-sequential-test.yml index 447f243cd1c..47bb5e053eb 100644 --- a/.github/workflows/ca-clone-sequential-test.yml +++ b/.github/workflows/ca-clone-sequential-test.yml @@ -984,6 +984,537 @@ jobs: diff expected output + #################################################################################################### + # Switch cert request ID generator to legacy2 and verify if serials + # have gaps when range is updated + # + # It should work like the legacy but with correct range. + - name: Stop the CAs + run: | + docker exec primary pki-server stop + docker exec secondary pki-server stop + + - name: Switch primary to legacy2 + run: | + docker exec primary pki-server ca-id-generator-update --type request legacy2 + docker exec primary pki-server ca-id-generator-update --type cert legacy2 + + - name: Check request range objects + run: | + tests/ca/bin/ca-request-range-objects.sh primaryds | tee output + + # request ranges should remain the same + cat > expected << EOF + SecurePort: 8443 + beginRange: 11 + endRange: 20 + host: primary.example.com + + SecurePort: 8443 + beginRange: 21 + endRange: 30 + host: secondary.example.com + + EOF + + diff expected output + + - name: Check request next range + run: | + tests/ca/bin/ca-request-next-range.sh primaryds | tee output + + # request nextRange should remain the same + cat > expected << EOF + nextRange: 31 + EOF + + diff expected output + + - name: Check cert range objects + run: | + tests/ca/bin/ca-cert-range-objects.sh primaryds | tee output + + # cert ranges should remain the same but converted from hex to decimal + # the range value for the primary move from 13-30 (hex) to 19-48 (dec) + cat > expected << EOF + SecurePort: 8443 + beginRange: 31 + endRange: 48 + host: secondary.example.com + + SecurePort: 8443 + beginRange: 19 + endRange: 48 + host: primary.example.com + + EOF + + diff expected output + + - name: Check cert next range + run: | + tests/ca/bin/ca-cert-next-range.sh primaryds | tee output + + # cert nextRange should remain the same + cat > expected << EOF + nextRange: 49 + EOF + + diff expected output + + - name: Switch secondary to legacy2 + run: | + docker exec secondary pki-server ca-id-generator-update --type request legacy2 + docker exec secondary pki-server ca-id-generator-update --type cert legacy2 + + - name: Start the CAs + run: | + docker exec primary pki-server start --wait + docker exec secondary pki-server start --wait + + - name: Check request range config in primary CA + run: | + tests/ca/bin/ca-request-range-config.sh primary | tee output + + cat > expected << EOF + dbs.beginRequestNumber=11 + dbs.endRequestNumber=15 + dbs.requestCloneTransferNumber=5 + dbs.requestIncrement=10 + dbs.requestLowWaterMark=5 + EOF + + diff expected output + + - name: Check request range config in secondary CA + run: | + tests/ca/bin/ca-request-range-config.sh secondary | tee output + + cat > expected << EOF + dbs.beginRequestNumber=21 + dbs.endRequestNumber=30 + dbs.requestCloneTransferNumber=5 + dbs.requestIncrement=10 + dbs.requestLowWaterMark=5 + EOF + + diff expected output + + - name: Check the radix for the new generator in all CAs + run: | + docker exec primary pki-server ca-config-show dbs.request.id.radix | tee output + docker exec secondary pki-server ca-config-show dbs.request.id.radix | tee -a output + docker exec primary pki-server ca-config-show dbs.cert.id.radix | tee -a output + docker exec secondary pki-server ca-config-show dbs.cert.id.radix | tee -a output + + cat > expected < expected << EOF + dbs.beginSerialNumber=0x13 + dbs.endSerialNumber=0x30 + dbs.serialCloneTransferNumber=0x9 + dbs.serialIncrement=0x12 + dbs.serialLowWaterMark=0x9 + EOF + + diff expected output + + - name: Check cert range config in secondary CA + run: | + tests/ca/bin/ca-cert-range-config.sh secondary | tee output + + cat > expected << EOF + dbs.beginSerialNumber=0x31 + dbs.endSerialNumber=0x48 + dbs.serialCloneTransferNumber=0x9 + dbs.serialIncrement=0x12 + dbs.serialLowWaterMark=0x9 + EOF + + diff expected output + + - name: Check request range objects + run: | + tests/ca/bin/ca-request-range-objects.sh primaryds | tee output + + cat > expected << EOF + SecurePort: 8443 + beginRange: 11 + endRange: 20 + host: primary.example.com + + SecurePort: 8443 + beginRange: 21 + endRange: 30 + host: secondary.example.com + + SecurePort: 8443 + beginRange: 31 + endRange: 40 + host: primary.example.com + + SecurePort: 8443 + beginRange: 41 + endRange: 50 + host: secondary.example.com + + EOF + + diff expected output + + - name: Check cert range objects + run: | + tests/ca/bin/ca-cert-range-objects.sh primaryds | tee output + + # cert ranges should remain the same but in dec. + # the range value for the primary move from 13-30 (hex) to 19-48 (dec) + # the range value for the secondary move from 31-48 (hex) to 49-72 (dec) + cat > expected << EOF + SecurePort: 8443 + beginRange: 19 + endRange: 48 + host: primary.example.com + + SecurePort: 8443 + beginRange: 49 + endRange: 72 + host: secondary.example.com + + EOF + + diff expected output + + - name: Check request repository + run: | + tests/ca/bin/ca-request-next-range.sh primaryds | tee output + + cat > expected << EOF + nextRange: 51 + EOF + + diff expected output + + - name: Check cert repository + run: | + tests/ca/bin/ca-cert-next-range.sh primaryds | tee output + + cat > expected << EOF + nextRange: 73 + EOF + + diff expected output + + #################################################################################################### + # Enroll additional certs updating the range + # + + - name: Enroll certs in primary and secondary + run: | + # Enroll until request range exhausted + for i in $(seq 1 10); do + docker exec primary pki \ + -n caadmin \ + ca-cert-issue \ + --profile caUserCert \ + --csr-file testuser.csr \ + --output-file testuser.crt + + docker exec primary openssl x509 -in testuser.crt -serial -noout + done + + for i in $(seq 1 10); do + docker exec secondary pki \ + -n caadmin \ + ca-cert-issue \ + --profile caUserCert \ + --csr-file testuser.csr \ + --output-file testuser.crt + + docker exec secondary openssl x509 -in testuser.crt -serial -noout + done + + - name: Allocate new ranges + run: | + docker exec primary pki \ + -n caadmin \ + ca-job-start \ + serialNumberUpdate + + docker exec secondary pki \ + -n caadmin \ + ca-job-start \ + serialNumberUpdate + + # wait for DS replication + sleep 5 + + + - name: Enroll certs in primary and secondary + run: | + # Enroll until request range exhausted + for i in $(seq 1 10); do + docker exec primary pki \ + -n caadmin \ + ca-cert-issue \ + --profile caUserCert \ + --csr-file testuser.csr \ + --output-file testuser.crt + + docker exec primary openssl x509 -in testuser.crt -serial -noout + done + + for i in $(seq 1 10); do + docker exec secondary pki \ + -n caadmin \ + ca-cert-issue \ + --profile caUserCert \ + --csr-file testuser.csr \ + --output-file testuser.crt + + docker exec secondary openssl x509 -in testuser.crt -serial -noout + done + + - name: Allocate new ranges + run: | + docker exec secondary pki \ + -n caadmin \ + ca-job-start \ + serialNumberUpdate + + docker exec primary pki \ + -n caadmin \ + ca-job-start \ + serialNumberUpdate + + - name: Enroll certs in secondary + run: | + # Enroll until request range exhausted + for i in $(seq 1 10); do + docker exec secondary pki \ + -n caadmin \ + ca-cert-issue \ + --profile caUserCert \ + --csr-file testuser.csr \ + --output-file testuser.crt + + docker exec secondary openssl x509 -in testuser.crt -serial -noout + done + + - name: Allocate new ranges + run: | + docker exec secondary pki \ + -n caadmin \ + ca-job-start \ + serialNumberUpdate + # wait for DS replication + sleep 5 + + - name: Check request range config in primary CA + run: | + tests/ca/bin/ca-request-range-config.sh primary | tee output + + cat > expected << EOF + dbs.beginRequestNumber=51 + dbs.endRequestNumber=60 + dbs.requestCloneTransferNumber=5 + dbs.requestIncrement=10 + dbs.requestLowWaterMark=5 + EOF + + diff expected output + + - name: Check request range config in secondary CA + run: | + tests/ca/bin/ca-request-range-config.sh secondary | tee output + + cat > expected << EOF + dbs.beginRequestNumber=71 + dbs.endRequestNumber=80 + dbs.requestCloneTransferNumber=5 + dbs.requestIncrement=10 + dbs.requestLowWaterMark=5 + EOF + + diff expected output + + - name: Check cert range config in primary CA + run: | + tests/ca/bin/ca-cert-range-config.sh primary | tee output + + cat > expected << EOF + dbs.beginSerialNumber=0x13 + dbs.endSerialNumber=0x30 + dbs.serialCloneTransferNumber=0x9 + dbs.serialIncrement=0x12 + dbs.serialLowWaterMark=0x9 + EOF + + diff expected output + + - name: Check cert range config in secondary CA + run: | + tests/ca/bin/ca-cert-range-config.sh secondary | tee output + + cat > expected << EOF + dbs.beginSerialNumber=0x49 + dbs.endSerialNumber=0x5a + dbs.serialCloneTransferNumber=0x9 + dbs.serialIncrement=0x12 + dbs.serialLowWaterMark=0x9 + EOF + + diff expected output + + - name: Check request range objects + run: | + tests/ca/bin/ca-request-range-objects.sh primaryds | tee output + + cat > expected << EOF + SecurePort: 8443 + beginRange: 11 + endRange: 20 + host: primary.example.com + + SecurePort: 8443 + beginRange: 21 + endRange: 30 + host: secondary.example.com + + SecurePort: 8443 + beginRange: 31 + endRange: 40 + host: primary.example.com + + SecurePort: 8443 + beginRange: 41 + endRange: 50 + host: secondary.example.com + + SecurePort: 8443 + beginRange: 51 + endRange: 60 + host: primary.example.com + + SecurePort: 8443 + beginRange: 61 + endRange: 70 + host: secondary.example.com + + SecurePort: 8443 + beginRange: 71 + endRange: 80 + host: secondary.example.com + + SecurePort: 8443 + beginRange: 81 + endRange: 90 + host: primary.example.com + + SecurePort: 8443 + beginRange: 91 + endRange: 100 + host: secondary.example.com + + EOF + + diff expected output + + - name: Check cert range objects + run: | + tests/ca/bin/ca-cert-range-objects.sh primaryds | tee output + + cat > expected << EOF + SecurePort: 8443 + beginRange: 19 + endRange: 48 + host: primary.example.com + + SecurePort: 8443 + beginRange: 49 + endRange: 72 + host: secondary.example.com + + SecurePort: 8443 + beginRange: 73 + endRange: 90 + host: secondary.example.com + + SecurePort: 8443 + beginRange: 91 + endRange: 108 + host: primary.example.com + + SecurePort: 8443 + beginRange: 109 + endRange: 126 + host: secondary.example.com + + EOF + + diff expected output + + - name: Check request repository + run: | + tests/ca/bin/ca-request-next-range.sh primaryds | tee output + + cat > expected << EOF + nextRange: 101 + EOF + + diff expected output + + - name: Check cert repository + run: | + tests/ca/bin/ca-cert-next-range.sh primaryds | tee output + + cat > expected << EOF + nextRange: 127 + EOF + + diff expected output + + - name: Check requests + run: | + docker exec secondary pki-server ca-cert-request-find | tee output + sed -n "s/^ *Request ID: *\(.*\)$/\1/p" output > actual + + # there should be 25 requests + seq 1 9 > expected # primary CA + seq 16 20 >> expected # secondary CA + seq 10 15 >> expected # primary CA + seq 21 30 >> expected # secondary CA + seq 31 40 >> expected # primary CA + seq 41 50 >> expected # secondary CA + seq 51 60 >> expected # primary CA + seq 61 70 >> expected # secondary CA + seq 71 80 >> expected # secondary CA + + diff expected actual + + - name: Check certs + run: | + docker exec primary pki-server ca-cert-find | tee output + sed -n "s/^ *Serial Number: *\(.*\)$/\1/p" output > actual + + + # There is only a permanent gap generated with legagy id generator + + seq 1 43 | while read n; do printf "0x%x\n" $n; done > expected + seq 49 84 | while read n; do printf "0x%x\n" $n; done >> expected + + diff expected actual + #################################################################################################### # Cleanup diff --git a/.github/workflows/ca-sequential-test.yml b/.github/workflows/ca-sequential-test.yml index 3a826ca53f3..372102c1e65 100644 --- a/.github/workflows/ca-sequential-test.yml +++ b/.github/workflows/ca-sequential-test.yml @@ -1143,6 +1143,363 @@ jobs: diff expected output + #################################################################################################### + # Switch cert request ID generator to legacy2 and verify if serials + # have gaps when range is updated + # + # It should work like the legacy but with correct range. + - name: Switch to legacy2 + run: | + docker exec pki pki-server stop + docker exec pki pki-server ca-id-generator-update --type request legacy2 + docker exec pki pki-server ca-id-generator-update --type cert legacy2 + docker exec pki pki-server start --wait + + + - name: Check request range config + run: | + tests/ca/bin/ca-request-range-config.sh pki | tee output + # request range should be the same + cat > expected << EOF + dbs.beginRequestNumber=31 + dbs.endRequestNumber=40 + dbs.requestCloneTransferNumber=5 + dbs.requestIncrement=10 + dbs.requestLowWaterMark=5 + EOF + + diff expected output + + - name: Check cert range config + run: | + tests/ca/bin/ca-cert-range-config.sh pki | tee output + + cat > expected << EOF + dbs.beginSerialNumber=0x37 + dbs.endSerialNumber=0x54 + dbs.serialCloneTransferNumber=0x9 + dbs.serialIncrement=0x12 + dbs.serialLowWaterMark=0x9 + EOF + + diff expected output + + - name: Check the radix in for the new generator + run: | + docker exec pki pki-server ca-config-show dbs.request.id.radix | tee output + docker exec pki pki-server ca-config-show dbs.cert.id.radix | tee -a output + + cat > expected < expected << EOF + nextRange: 51 + EOF + + diff expected output + + - name: Check cert repository + run: | + tests/ca/bin/ca-cert-next-range.sh ds | tee output + + cat > expected << EOF + nextRange: 85 + EOF + + diff expected output + + - name: Check request range objects + run: | + tests/ca/bin/ca-request-range-objects.sh ds | tee output + + # new request range should be 31 - 40 decimal (total: 10) + cat > expected << EOF + SecurePort: 8443 + beginRange: 11 + endRange: 20 + host: pki.example.com + + SecurePort: 8443 + beginRange: 21 + endRange: 30 + host: pki.example.com + + SecurePort: 8443 + beginRange: 31 + endRange: 40 + host: pki.example.com + + SecurePort: 8443 + beginRange: 41 + endRange: 50 + host: pki.example.com + + EOF + + diff expected output + + - name: Check cert range objects + run: | + tests/ca/bin/ca-cert-range-objects.sh ds | tee output + + # new cert range should be the same but converted to decimal + # first range move from 19-36 (hex) to 25-54 (dec) + # second range move from 37-54 (hex) to 55-84 (dec) + cat > expected << EOF + SecurePort: 8443 + beginRange: 25 + endRange: 54 + host: pki.example.com + + SecurePort: 8443 + beginRange: 55 + endRange: 84 + host: pki.example.com + + EOF + + diff expected output + + #################################################################################################### + # Enroll additional certs updating the range + # + + - name: Enroll additional certs + run: | + # Enroll until request range exhausted + for i in $(seq 1 9); do + docker exec pki pki \ + -n caadmin \ + ca-cert-issue \ + --profile caUserCert \ + --csr-file testuser.csr \ + --output-file testuser.crt + + docker exec pki openssl x509 -in testuser.crt -serial -noout + done + docker exec pki pki -n caadmin ca-job-start serialNumberUpdate + # Enroll until request range exhausted + for i in $(seq 1 10); do + docker exec pki pki \ + -n caadmin \ + ca-cert-issue \ + --profile caUserCert \ + --csr-file testuser.csr \ + --output-file testuser.crt + + docker exec pki openssl x509 -in testuser.crt -serial -noout + done + docker exec pki pki -n caadmin ca-job-start serialNumberUpdate + # Enroll until request range exhausted + for i in $(seq 1 10); do + docker exec pki pki \ + -n caadmin \ + ca-cert-issue \ + --profile caUserCert \ + --csr-file testuser.csr \ + --output-file testuser.crt + + docker exec pki openssl x509 -in testuser.crt -serial -noout + done + docker exec pki pki -n caadmin ca-job-start serialNumberUpdate + # Enroll until request range exhausted + for i in $(seq 1 10); do + docker exec pki pki \ + -n caadmin \ + ca-cert-issue \ + --profile caUserCert \ + --csr-file testuser.csr \ + --output-file testuser.crt + + docker exec pki openssl x509 -in testuser.crt -serial -noout + done + docker exec pki pki -n caadmin ca-job-start serialNumberUpdate + # Enroll until request range exhausted + for i in $(seq 1 10); do + docker exec pki pki \ + -n caadmin \ + ca-cert-issue \ + --profile caUserCert \ + --csr-file testuser.csr \ + --output-file testuser.crt + + docker exec pki openssl x509 -in testuser.crt -serial -noout + done + docker exec pki pki -n caadmin ca-job-start serialNumberUpdate + + - name: Check request range config + run: | + tests/ca/bin/ca-request-range-config.sh pki | tee output + + cat > expected << EOF + dbs.beginRequestNumber=81 + dbs.endRequestNumber=90 + dbs.requestCloneTransferNumber=5 + dbs.requestIncrement=10 + dbs.requestLowWaterMark=5 + EOF + + diff expected output + + - name: Check cert range config + run: | + tests/ca/bin/ca-cert-range-config.sh pki | tee output + + cat > expected << EOF + dbs.beginSerialNumber=0x67 + dbs.endSerialNumber=0x78 + dbs.serialCloneTransferNumber=0x9 + dbs.serialIncrement=0x12 + dbs.serialLowWaterMark=0x9 + EOF + + diff expected output + + - name: Check request repository + run: | + tests/ca/bin/ca-request-next-range.sh ds | tee output + + cat > expected << EOF + nextRange: 101 + EOF + + diff expected output + + - name: Check cert repository + run: | + tests/ca/bin/ca-cert-next-range.sh ds | tee output + + cat > expected << EOF + nextRange: 121 + EOF + + diff expected output + + - name: Check request range objects + run: | + tests/ca/bin/ca-request-range-objects.sh ds | tee output + + cat > expected << EOF + SecurePort: 8443 + beginRange: 11 + endRange: 20 + host: pki.example.com + + SecurePort: 8443 + beginRange: 21 + endRange: 30 + host: pki.example.com + + SecurePort: 8443 + beginRange: 31 + endRange: 40 + host: pki.example.com + + SecurePort: 8443 + beginRange: 41 + endRange: 50 + host: pki.example.com + + SecurePort: 8443 + beginRange: 51 + endRange: 60 + host: pki.example.com + + SecurePort: 8443 + beginRange: 61 + endRange: 70 + host: pki.example.com + + SecurePort: 8443 + beginRange: 71 + endRange: 80 + host: pki.example.com + + SecurePort: 8443 + beginRange: 81 + endRange: 90 + host: pki.example.com + + SecurePort: 8443 + beginRange: 91 + endRange: 100 + host: pki.example.com + + EOF + + diff expected output + + - name: Check cert range objects + run: | + tests/ca/bin/ca-cert-range-objects.sh ds | tee output + + cat > expected << EOF + SecurePort: 8443 + beginRange: 25 + endRange: 54 + host: pki.example.com + + SecurePort: 8443 + beginRange: 55 + endRange: 84 + host: pki.example.com + + SecurePort: 8443 + beginRange: 85 + endRange: 102 + host: pki.example.com + + SecurePort: 8443 + beginRange: 103 + endRange: 120 + host: pki.example.com + + EOF + + diff expected output + + #################################################################################################### + # Checking request no gap should be present after switching to legacy2 + # + - name: Check requests + run: | + docker exec pki pki-server ca-cert-request-find | tee output + + sed -n "s/^ *Request ID: *\(.*\)$/\1/p" output > actual + + # there should be 40 requests (30 existing + 10 new) + seq 1 89 > expected + + diff expected actual + + #################################################################################################### + # Checking certs no gap should be present after switching to legacy2 + # so the last gap is between 32 and 39 + # + - name: Check certs + run: | + docker exec pki pki-server ca-cert-find | tee output + + sed -n "s/^ *Serial Number: *\(.*\)$/\1/p" output > actual + + # there should be 39 certs (29 existing + 10 new) + # but due to a bug the serial numbers have a gap + + # seq 1 39 | while read n; do printf "0x%x\n" $n; done > expected + seq 9 42 | while read n; do printf "0x%x\n" $n; done > expected + seq 55 108 | while read n; do printf "0x%x\n" $n; done >> expected + + diff expected actual + #################################################################################################### # Enroll a cert with RSNv3 #