예제 #1
0
    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)
예제 #2
0
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)
예제 #3
0
    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"])
예제 #4
0
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)
예제 #5
0
    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)
예제 #6
0
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}")
예제 #7
0
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"])
예제 #8
0
def test_decode_text(encoded_text, key, expected):
    from jans.pycloudlib.utils import decode_text
    assert decode_text(encoded_text, key) == expected
예제 #9
0
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"])