Skip to content

Commit

Permalink
Add pki-server <subsystem>-db-repl-enable
Browse files Browse the repository at this point in the history
The pki-server <subsystem>-db-repl-enable has been added
to enable replication on a single DS instance. This command
replaces the SubsystemDBReplicationSetupCLI which enables
replication both on the DS master and the replica at the
same time.

The test for CA cloning with replicated DS has been updated
to use the new command.
  • Loading branch information
edewata committed Dec 14, 2023
1 parent 335c870 commit a9e002f
Show file tree
Hide file tree
Showing 7 changed files with 335 additions and 287 deletions.
42 changes: 20 additions & 22 deletions .github/workflows/ca-clone-replicated-ds-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,16 +151,15 @@ jobs:
- name: Enable replication on primary DS
run: |
docker exec primaryds dsconf \
-D "cn=Directory Manager" \
-w Secret.123 \
ldap://primaryds.example.com:3389 \
replication enable \
--suffix=dc=ca,dc=pki,dc=example,dc=com \
--role=supplier \
--replica-id=1 \
--bind-dn="cn=Replication Manager,cn=config" \
--bind-passwd=Secret.123
docker exec primary pki-server ca-db-repl-enable \
--url ldap://primaryds.example.com:3389 \
--bind-dn "cn=Directory Manager" \
--bind-password Secret.123 \
--replica-bind-dn "cn=Replication Manager,cn=config" \
--replica-bind-password Secret.123 \
--replica-id 1 \
--suffix dc=ca,dc=pki,dc=example,dc=com \
-v
# check replication manager
docker exec primaryds ldapsearch \
Expand All @@ -186,16 +185,15 @@ jobs:
- name: Enable replication on secondary DS
run: |
docker exec secondaryds dsconf \
-D "cn=Directory Manager" \
-w Secret.123 \
ldap://secondaryds.example.com:3389 \
replication enable \
--suffix=dc=ca,dc=pki,dc=example,dc=com \
--role=supplier \
--replica-id=2 \
--bind-dn="cn=Replication Manager,cn=config" \
--bind-passwd=Secret.123
docker exec secondary pki-server ca-db-repl-enable \
--url ldap://secondaryds.example.com:3389 \
--bind-dn "cn=Directory Manager" \
--bind-password Secret.123 \
--replica-bind-dn "cn=Replication Manager,cn=config" \
--replica-bind-password Secret.123 \
--replica-id 2 \
--suffix dc=ca,dc=pki,dc=example,dc=com \
-v
# check replication manager
docker exec secondaryds ldapsearch \
Expand All @@ -221,7 +219,7 @@ jobs:
- name: Create replication agreement on primary DS
run: |
docker exec secondary pki-server ca-db-repl-agmt-add \
docker exec primary pki-server ca-db-repl-agmt-add \
--url ldap://primaryds.example.com:3389 \
--bind-dn "cn=Directory Manager" \
--bind-password Secret.123 \
Expand Down Expand Up @@ -269,7 +267,7 @@ jobs:
- name: Initializing replication agreement
run: |
docker exec secondary pki-server ca-db-repl-agmt-init \
docker exec primary pki-server ca-db-repl-agmt-init \
--url ldap://primaryds.example.com:3389 \
--bind-dn "cn=Directory Manager" \
--bind-password Secret.123 \
Expand Down
144 changes: 144 additions & 0 deletions base/server/python/pki/server/cli/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -1410,9 +1410,153 @@ def __init__(self, parent):
subsystem=parent.parent.name.upper()))

self.parent = parent
self.add_module(SubsystemDBReplicationEnableCLI(self))
self.add_module(SubsystemDBReplicationAgreementCLI(self))


class SubsystemDBReplicationEnableCLI(pki.cli.CLI):
'''
Enable {subsystem} database replication
'''

help = '''\
Usage: pki-server {subsystem}-db-repl-enable [OPTIONS]
-i, --instance <instance ID> Instance ID (default: pki-tomcat)
--url <URL> Database URL
--bind-dn <DN> Database bind DN
--bind-password <password> Database bind password
--replica-bind-dn <DN> Replica bind DN
--replica-bind-password <password> Replica bind password
--replica-id <ID> Replica ID
--suffix <DN> Database suffix
-v, --verbose Run in verbose mode.
--debug Run in debug mode.
--help Show help message.
'''

def __init__(self, parent):
super(SubsystemDBReplicationEnableCLI, self).__init__(
'enable',
inspect.cleandoc(self.__class__.__doc__).format(
subsystem=parent.parent.parent.name.upper()))

self.parent = parent

def print_help(self):
print(textwrap.dedent(self.__class__.help).format(
subsystem=self.parent.parent.parent.name))

def execute(self, argv):
try:
opts, _ = getopt.gnu_getopt(argv, 'i:v', [
'instance=',
'url=', 'bind-dn=', 'bind-password=',
'replica-bind-dn=', 'replica-bind-password=',
'replica-id=', 'suffix=',
'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
url = None
bind_dn = None
bind_password = None
replica_bind_dn = None
replica_bind_password = None
replica_id = None
suffix = None

for o, a in opts:
if o in ('-i', '--instance'):
instance_name = a

elif o == '--url':
url = urllib.parse.urlparse(a)

elif o == '--bind-dn':
bind_dn = a

elif o == '--bind-password':
bind_password = a

elif o == '--replica-bind-dn':
replica_bind_dn = a

elif o == '--replica-bind-password':
replica_bind_password = a

elif o == '--replica-id':
replica_id = a

elif o == '--suffix':
suffix = 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)

# user must provide the replica ID is required since
# in the future the auto-generated replica ID will no
# longer be supported

if not replica_id:
logger.error('Missing replica ID')
sys.exit(1)

instance = pki.server.instance.PKIInstance(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)

ldap_config = {}

if url.scheme == 'ldaps':
ldap_config['ldapconn.secureConn'] = 'true'
else:
ldap_config['ldapconn.secureConn'] = 'false'

ldap_config['ldapconn.host'] = url.hostname
ldap_config['ldapconn.port'] = str(url.port)

ldap_config['ldapauth.authtype'] = 'BasicAuth'
ldap_config['ldapauth.bindDN'] = bind_dn
ldap_config['ldapauth.bindPassword'] = bind_password

ldap_config['basedn'] = suffix

subsystem.enable_replication(
ldap_config,
replica_bind_dn,
replica_bind_password,
replica_id)


class SubsystemDBReplicationAgreementCLI(pki.cli.CLI):
'''
{subsystem} replication agreement management commands
Expand Down
24 changes: 18 additions & 6 deletions base/server/python/pki/server/deployment/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1593,12 +1593,6 @@ def setup_database(self, subsystem, master_config):

logger.info('- replication security: %s', replication_security)

subsystem.setup_replication(
master_config['Properties'],
master_replication_port=master_replication_port,
replica_replication_port=replica_replication_port,
replication_security=replication_security)

# get master database config

master_ldap_config = {}
Expand Down Expand Up @@ -1673,6 +1667,24 @@ def setup_database(self, subsystem, master_config):
replica_agreement_name
replica_bind_password = self.instance.get_password('replicationdb')

logger.info('Enable replication on master')

# TODO: provide param to specify the replica ID for the master
subsystem.enable_replication(
master_ldap_config,
master_bind_dn,
master_bind_password,
None)

logger.info('Enable replication on replica')

# TODO: provide param to specify the replica ID for the replica
subsystem.enable_replication(
replica_ldap_config,
replica_bind_dn,
replica_bind_password,
None)

logger.info('Adding master replication agreement')
logger.info('- replica URL: %s', replica_url)

Expand Down
41 changes: 21 additions & 20 deletions base/server/python/pki/server/subsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -1296,40 +1296,41 @@ def revoke_database_access(
as_current_user=as_current_user,
capture_output=True)

def setup_replication(
def enable_replication(
self,
master_config,
master_replication_port=None,
replica_replication_port=None,
replication_security=None):
ldap_config,
replica_bind_dn,
replica_bind_password,
replica_id):

tmpdir = tempfile.mkdtemp()
try:
master_config_file = os.path.join(tmpdir, 'master.conf')
pki.util.store_properties(master_config_file, master_config)

cmd = [self.name + '-db-repl-setup']

if master_replication_port:
cmd.extend(['--master-replication-port', master_replication_port])
ldap_config_file = os.path.join(tmpdir, 'ldap.conf')
pki.util.store_properties(ldap_config_file, ldap_config)
pki.util.chown(tmpdir, self.instance.uid, self.instance.gid)

if replica_replication_port:
cmd.extend(['--replica-replication-port', replica_replication_port])
password_file = os.path.join(tmpdir, 'password.txt')
with open(password_file, 'w', encoding='utf-8') as f:
f.write(replica_bind_password)
pki.util.chown(password_file, self.instance.uid, self.instance.gid)

if replication_security:
cmd.extend(['--replication-security', replication_security])
cmd = [
self.name + '-db-repl-enable',
'--ldap-config', ldap_config_file,
'--replica-bind-dn', replica_bind_dn,
'--replica-bind-password-file', password_file
]

if master_config_file:
cmd.extend(['--master-config', master_config_file])
if replica_id:
cmd.extend(['--replica-id', replica_id])

if logger.isEnabledFor(logging.DEBUG):
cmd.append('--debug')

elif logger.isEnabledFor(logging.INFO):
cmd.append('--verbose')

# run as current user so it can read the input file
self.run(cmd, as_current_user=True)
self.run(cmd)

finally:
shutil.rmtree(tmpdir)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class SubsystemDBReplicationCLI extends CLI {
public SubsystemDBReplicationCLI(CLI parent) {
super("repl", parent.parent.name.toUpperCase() + " database replication management commands", parent);

addModule(new SubsystemDBReplicationSetupCLI(this));
addModule(new SubsystemDBReplicationEnableCLI(this));
addModule(new SubsystemDBReplicationAgreementCLI(this));
}
}
Loading

0 comments on commit a9e002f

Please sign in to comment.