def to_file(self, key: str, dest: str, decode: bool = False, binary_mode: bool = False) -> AnyStr: """Pull secret and write to a file. Example: .. code-block:: python # assuming there is secret with key ``server_cert`` that stores # server cert needed to be fetched as ``/etc/certs/server.crt`` # file. SecretManager().to_file("server_cert", "/etc/certs/server.crt") # assuming there is secret with key ``server_jks`` that stores # server keystore needed to be fetched as ``/etc/certs/server.jks`` # file. SecretManager().to_file( "server_jks", "/etc/certs/server.jks", decode=True, binary_mode=True, ) :params key: Key name in secret backend. :params dest: Absolute path to file to write the secret to. :params decode: Decode the content of the secret. :params binary_mode: Write the file as binary. """ mode = "w" if binary_mode: mode = "wb" # always decodes the bytes decode = True value = self.adapter.get(key) if decode: salt = self.adapter.get("encoded_salt") try: value = decode_text(value, salt).decode() except UnicodeDecodeError: # likely bytes from a binary value = decode_text(value, salt).decode("ISO-8859-1") with open(dest, mode) as f: if binary_mode: # convert to bytes value = value.encode("ISO-8859-1") f.write(value)
def main(): # check how many member in ldap cluster, peers_num = len(peers_from_serf_membership()) if peers_num == 0: sys.exit(1) elif peers_num == 1: # if there's only 1 alive member, mark the server as ready to allow # data injection to persistence sys.exit(0) else: # if there are more than 1 instances, determine the server readiness by # checking entries in persistence manager = get_manager() host = "localhost:1636" user = manager.config.get("ldap_binddn") password = decode_text( manager.secret.get("encoded_ox_ldap_pw"), manager.secret.get("encoded_salt"), ) result = get_ldap_entries(host, user, password) if result: sys.exit(0) else: sys.exit(1)
def delete_instance_key(): export_ads_certificate() cmd = "openssl x509 -fingerprint -md5 -noout -in /opt/opendj/config/ads-cert.crt" out, err, code = exec_cmd(cmd) if code != 0: err = err or out logger.error( f"Unable to get ads-cert fingerprint; reason={err.decode()}") sys.exit(1) cfg_key = out.decode().split("=")[-1].replace(":", "") host = "localhost:1636" user = manager.config.get("ldap_binddn") password = decode_text(manager.secret.get("encoded_ox_ldap_pw"), manager.secret.get("encoded_salt")) ldap_server = ldap3.Server(host, 1636, use_ssl=True) with ldap3.Connection(ldap_server, user, password) as conn: conn.delete( f"ds-cfg-key-id={cfg_key},cn=instance keys,cn=admin data") if conn.result["description"] != "success": logger.warning(conn.result["message"])
def install_opendj(): logger.info("Installing OpenDJ.") # 1) render opendj-setup.properties # admin_port = 4444 admin_port = os.environ.get("CN_LDAP_ADVERTISE_ADMIN_PORT", "4444") ctx = { "ldap_hostname": guess_host_addr(), "ldap_port": manager.config.get("ldap_port"), "ldaps_port": manager.config.get("ldaps_port"), "ldap_jmx_port": 1689, "ldap_admin_port": admin_port, "opendj_ldap_binddn": manager.config.get("ldap_binddn"), "ldapPassFn": DEFAULT_ADMIN_PW_PATH, "ldap_backend_type": "je", } with open("/app/templates/opendj-setup.properties") as fr: content = fr.read() % ctx with open("/opt/opendj/opendj-setup.properties", "w") as fw: fw.write(content) # 2) run installer keypasswd = decode_text( manager.secret.get("encoded_ldapTrustStorePass"), manager.secret.get("encoded_salt"), ).decode() cmd = " ".join([ "/opt/opendj/setup", "--no-prompt", "--cli", "--acceptLicense", "--propertiesFilePath /opt/opendj/opendj-setup.properties", "--usePkcs12keyStore /etc/certs/opendj.pkcs12", f"--keyStorePassword {keypasswd}", "--doNotStart", ]) out, err, code = exec_cmd(cmd) if code and err: logger.warning(err.decode()) if all([ os.environ.get("JAVA_VERSION", "") >= "1.8.0", os.path.isfile("/opt/opendj/config/config.ldif") ]): with open("/opt/opendj/config/java.properties", "a") as f: status_arg = "\nstatus.java-args=-Xms8m -client -Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true" max_ram_percentage = os.environ.get("CN_MAX_RAM_PERCENTAGE", "75.0") repl_arg = f"\ndsreplication.java-args=-client -Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true -XX:+UseContainerSupport -XX:MaxRAMPercentage={max_ram_percentage}" args = "".join([status_arg, repl_arg]) f.write(args)
def __init__(self, manager, host="", user="", password=""): """ Initialize instance. :params manager: An instance of :class:`~pygluu.containerlib.manager._Manager`. """ host = host or os.environ.get("CN_LDAP_URL", "localhost:1636") # we only need host part as port will be resolved from env that controls # SSL or non-SSL connetion host = extract_ldap_host(host) user = user or manager.config.get("ldap_binddn") password = password or decode_text( manager.secret.get("encoded_ox_ldap_pw"), manager.secret.get("encoded_salt") ) use_ssl = as_boolean(os.environ.get("CN_LDAP_USE_SSL", True)) port = resolve_ldap_port() self.server = Server(host, port=port, use_ssl=use_ssl) self.conn = Connection(self.server, user, password)
def decode_string(text, salt_file, salt_literal): salt = "" if salt_literal: salt = salt_literal elif salt_file: with click.open_file(salt_file, "r") as f: salt = f.read().split(" = ")[-1].strip() else: manager = get_manager() try: salt = manager.secret.get("encoded_salt") except Exception as exc: # noqa: B902 click.echo(f"Unable to get salt from secrets; reason={exc}") if not salt: raise click.Abort() try: txt = decode_text(text, salt) click.echo(txt) except ValueError as exc: raise click.ClickException(f"Unable to decode given string; reason={exc}")
def configure_opendj_indexes(): logger.info("Configuring indexes for available backends.") with open("/app/templates/index.json") as f: data = json.load(f) host = "localhost:1636" user = manager.config.get("ldap_binddn") password = decode_text( manager.secret.get("encoded_ox_ldap_pw"), manager.secret.get("encoded_salt"), ) ldap_server = ldap3.Server(host, 1636, use_ssl=True) backends = ["userRoot", "metric"] if require_site(): backends.append("site") with ldap3.Connection(ldap_server, user, password) as conn: for attr_map in data: for backend in attr_map["backend"]: if backend not in backends: continue dn = f"ds-cfg-attribute={attr_map['attribute']},cn=Index,ds-cfg-backend-id={backend},cn=Backends,cn=config" attrs = { 'objectClass': ['top', 'ds-cfg-backend-index'], 'ds-cfg-attribute': [attr_map['attribute']], 'ds-cfg-index-type': attr_map['index'], 'ds-cfg-index-entry-limit': ['4000'], } conn.add(dn, attributes=attrs) if conn.result["description"] != "success": logger.warning(conn.result["message"])
def test_decode_text(encoded_text, key, expected): from jans.pycloudlib.utils import decode_text assert decode_text(encoded_text, key) == expected
def configure_opendj(): logger.info("Configuring OpenDJ.") host = "localhost:1636" user = manager.config.get("ldap_binddn") password = decode_text( manager.secret.get("encoded_ox_ldap_pw"), manager.secret.get("encoded_salt"), ) ldap_server = ldap3.Server(host, 1636, use_ssl=True) mods = [ ('ds-cfg-backend-id=userRoot,cn=Backends,cn=config', 'ds-cfg-db-cache-percent', '70', ldap3.MODIFY_REPLACE), ('cn=config', 'ds-cfg-single-structural-objectclass-behavior', 'accept', ldap3.MODIFY_REPLACE), ('cn=config', 'ds-cfg-reject-unauthenticated-requests', 'true', ldap3.MODIFY_REPLACE), ('cn=Default Password Policy,cn=Password Policies,cn=config', 'ds-cfg-allow-pre-encoded-passwords', 'true', ldap3.MODIFY_REPLACE), ('cn=Default Password Policy,cn=Password Policies,cn=config', 'ds-cfg-default-password-storage-scheme', 'cn=Salted SHA-512,cn=Password Storage Schemes,cn=config', ldap3.MODIFY_REPLACE), ('cn=File-Based Audit Logger,cn=Loggers,cn=config', 'ds-cfg-enabled', 'true', ldap3.MODIFY_REPLACE), ('cn=LDAP Connection Handler,cn=Connection Handlers,cn=config', 'ds-cfg-enabled', 'false', ldap3.MODIFY_REPLACE), ('cn=JMX Connection Handler,cn=Connection Handlers,cn=config', 'ds-cfg-enabled', 'false', ldap3.MODIFY_REPLACE), ('cn=Access Control Handler,cn=config', 'ds-cfg-global-aci', '(targetattr!="userPassword||authPassword||debugsearchindex||changes||changeNumber||changeType||changeTime||targetDN||newRDN||newSuperior||deleteOldRDN")(version 3.0; acl "Anonymous read access"; allow (read,search,compare) userdn="ldap:///anyone";)', ldap3.MODIFY_DELETE), ("cn=Core Schema,cn=Schema Providers,cn=config", "ds-cfg-allow-zero-length-values-directory-string", "true", ldap3.MODIFY_REPLACE), ] with ldap3.Connection(ldap_server, user, password) as conn: for dn, attr, value, mod_type in mods: conn.modify(dn, {attr: [mod_type, value]}) if conn.result["description"] != "success": logger.warning(conn.result["message"]) # Create uniqueness for attrbiutes with ldap3.Connection(ldap_server, user, password) as conn: attrs = [ ("mail", "Unique mail address"), ("uid", "Unique uid entry"), ] for attr, cn in attrs: conn.add( f'cn={cn},cn=Plugins,cn=config', attributes={ 'objectClass': ['top', 'ds-cfg-plugin', 'ds-cfg-unique-attribute-plugin'], 'ds-cfg-java-class': ['org.opends.server.plugins.UniqueAttributePlugin'], 'ds-cfg-enabled': ['true'], 'ds-cfg-plugin-type': [ 'postoperationadd', 'postoperationmodify', 'postoperationmodifydn', 'postsynchronizationadd', 'postsynchronizationmodify', 'postsynchronizationmodifydn', 'preoperationadd', 'preoperationmodify', 'preoperationmodifydn', ], 'ds-cfg-type': [attr], 'cn': [cn], 'ds-cfg-base-dn': ["o=jans"], }, ) if conn.result["description"] != "success": logger.warning(conn.result["message"])