Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pki-server <subsystem>-db-repl-enable #4639

Merged
merged 1 commit into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading