def set_iam_properties(
    info: RedshiftProperty,
    user: str,
    host: str,
    database: str,
    port: int,
    password: str,
    source_address: typing.Optional[str],
    unix_sock: typing.Optional[str],
    ssl: bool,
    sslmode: str,
    timeout: typing.Optional[int],
    max_prepared_statements: int,
    tcp_keepalive: bool,
    application_name: typing.Optional[str],
    replication: typing.Optional[str],
    idp_host: typing.Optional[str],
    db_user: typing.Optional[str],
    iam: bool,
    app_id: typing.Optional[str],
    app_name: str,
    preferred_role: typing.Optional[str],
    principal_arn: typing.Optional[str],
    credentials_provider: typing.Optional[str],
    region: typing.Optional[str],
    cluster_identifier: typing.Optional[str],
    client_id: typing.Optional[str],
    idp_tenant: typing.Optional[str],
    client_secret: typing.Optional[str],
    partner_sp_id: typing.Optional[str],
    idp_response_timeout: int,
    listen_port: int,
    login_url: typing.Optional[str],
    auto_create: bool,
    db_groups: typing.Optional[typing.List[str]],
    force_lowercase: bool,
    allow_db_user_override: bool,
) -> None:
    if info is None:
        raise InterfaceError(
            "Invalid connection property setting. info must be specified")
    # IAM requires an SSL connection to work.
    # Make sure that is set to SSL level VERIFY_CA or higher.
    info.ssl = ssl
    if info.ssl is True:
        if sslmode == SSLMode.VERIFY_CA.value:
            info.sslmode = SSLMode.VERIFY_CA.value
        elif sslmode == SSLMode.VERIFY_FULL.value:
            info.sslmode = SSLMode.VERIFY_FULL.value
        else:
            info.sslmode = SSLMode.VERIFY_CA.value
    else:
        info.sslmode = ""

    if (info.ssl is False) and (iam is True):
        raise InterfaceError(
            "Invalid connection property setting. SSL must be enabled when using IAM"
        )
    else:
        info.iam = iam

    if (info.iam is False) and (credentials_provider is not None):
        raise InterfaceError(
            "Invalid connection property setting. IAM must be enabled when using credentials "
            "via identity provider")
    elif (info.iam is True) and (credentials_provider is None):
        raise InterfaceError(
            "Invalid connection property setting. "
            "Credentials provider cannot be None when IAM is enabled")
    else:
        info.credentials_provider = credentials_provider

    if user is None:
        raise InterfaceError(
            "Invalid connection property setting. user must be specified")
    if host is None:
        raise InterfaceError(
            "Invalid connection property setting. host must be specified")
    if database is None:
        raise InterfaceError(
            "Invalid connection property setting. database must be specified")
    if port is None:
        raise InterfaceError(
            "Invalid connection property setting. port must be specified")
    if password is None:
        raise InterfaceError(
            "Invalid connection property setting. password must be specified")

    # basic driver parameters
    info.user_name = user
    info.host = host
    info.db_name = database
    info.port = port
    info.password = password
    info.source_address = source_address
    info.unix_sock = unix_sock
    info.timeout = timeout
    info.max_prepared_statements = max_prepared_statements
    info.tcp_keepalive = tcp_keepalive
    info.application_name = application_name
    info.replication = replication

    # Idp parameters
    info.idp_host = idp_host
    info.db_user = db_user
    info.app_id = app_id
    info.app_name = app_name
    info.preferred_role = preferred_role
    info.principal = principal_arn
    # Regions.fromName(string) requires the string to be lower case and in this format:
    # E.g. "us-west-2"
    info.region = region
    # cluster_identifier parameter is required
    info.cluster_identifier = cluster_identifier
    info.auto_create = auto_create
    info.db_groups = db_groups
    info.force_lowercase = force_lowercase
    info.allow_db_user_override = allow_db_user_override

    # Azure specified parameters
    info.client_id = client_id
    info.idp_tenant = idp_tenant
    info.client_secret = client_secret

    # Browser idp parameters
    info.idp_response_timeout = idp_response_timeout
    info.listen_port = listen_port
    info.login_url = login_url
    info.partner_sp_id = partner_sp_id

    if info.iam is True:
        set_iam_credentials(info)
    else:
        return
Example #2
0
    def set_iam_properties(
        info: RedshiftProperty,
        user: str,
        host: str,
        database: str,
        port: int,
        password: str,
        source_address: typing.Optional[str],
        unix_sock: typing.Optional[str],
        ssl: bool,
        sslmode: str,
        timeout: typing.Optional[int],
        max_prepared_statements: int,
        tcp_keepalive: bool,
        application_name: typing.Optional[str],
        replication: typing.Optional[str],
        idp_host: typing.Optional[str],
        db_user: typing.Optional[str],
        iam: bool,
        app_id: typing.Optional[str],
        app_name: str,
        preferred_role: typing.Optional[str],
        principal_arn: typing.Optional[str],
        access_key_id: typing.Optional[str],
        secret_access_key: typing.Optional[str],
        session_token: typing.Optional[str],
        profile: typing.Optional[str],
        credentials_provider: typing.Optional[str],
        region: typing.Optional[str],
        cluster_identifier: typing.Optional[str],
        client_id: typing.Optional[str],
        idp_tenant: typing.Optional[str],
        client_secret: typing.Optional[str],
        partner_sp_id: typing.Optional[str],
        idp_response_timeout: int,
        listen_port: int,
        login_url: typing.Optional[str],
        auto_create: bool,
        db_groups: typing.List[str],
        force_lowercase: bool,
        allow_db_user_override: bool,
        client_protocol_version: int,
        database_metadata_current_db_only: bool,
        ssl_insecure: typing.Optional[bool],
        web_identity_token: typing.Optional[str],
        role_session_name: typing.Optional[str],
        role_arn: typing.Optional[str],
    ) -> None:
        """
        Helper function to handle IAM connection properties and ensure required parameters are specified.
        Parameters
        """
        if info is None:
            raise InterfaceError(
                "Invalid connection property setting. info must be specified")
        # IAM requires an SSL connection to work.
        # Make sure that is set to SSL level VERIFY_CA or higher.
        info.ssl = ssl
        if info.ssl is True:
            if sslmode not in SupportedSSLMode.list():
                info.sslmode = SupportedSSLMode.default()
                _logger.debug(
                    "A non-supported value: {} was provides for sslmode. Falling back to default value: {}"
                    .format(sslmode, SupportedSSLMode.default()))
            else:
                info.sslmode = sslmode
        else:
            info.sslmode = ""

        if (info.ssl is False) and (iam is True):
            raise InterfaceError(
                "Invalid connection property setting. SSL must be enabled when using IAM"
            )
        else:
            info.iam = iam

        if (info.iam is False) and (ssl_insecure is not None):
            raise InterfaceError(
                "Invalid connection property setting. IAM must be enabled when using ssl_insecure"
            )
        elif (info.iam is False) and any(
            (credentials_provider, access_key_id, secret_access_key,
             session_token, profile)):
            raise InterfaceError(
                "Invalid connection property setting. IAM must be enabled when using credential_provider, "
                "AWS credentials, or AWS profile")
        elif info.iam is True:
            if cluster_identifier is None:
                raise InterfaceError(
                    "Invalid connection property setting. cluster_identifier must be provided when IAM is enabled"
                )
            if not any((credentials_provider, access_key_id, secret_access_key,
                        session_token, profile)):
                raise InterfaceError(
                    "Invalid connection property setting. Credentials provider, AWS credentials, or AWS profile must be"
                    " provided when IAM is enabled")
            elif credentials_provider is not None:
                if any((access_key_id, secret_access_key, session_token,
                        profile)):
                    raise InterfaceError(
                        "Invalid connection property setting. It is not valid to provide both Credentials provider and "
                        "AWS credentials or AWS profile")
                else:
                    info.credentials_provider = credentials_provider
            elif profile is not None:
                if any((access_key_id, secret_access_key, session_token)):
                    raise InterfaceError(
                        "Invalid connection property setting. It is not valid to provide any of access_key_id, "
                        "secret_access_key, or session_token when profile is provided"
                    )
                else:
                    info.profile = profile
            elif access_key_id is not None:
                info.access_key_id = access_key_id

                if secret_access_key is not None:
                    info.secret_access_key = secret_access_key
                # secret_access_key can be provided in the password field so it is hidden from applications such as
                # SQL Workbench.
                elif password != "":
                    info.secret_access_key = password
                else:
                    raise InterfaceError(
                        "Invalid connection property setting. "
                        "secret access key must be provided in either secret_access_key or password field"
                    )

                if session_token is not None:
                    info.session_token = session_token
            elif secret_access_key is not None:
                raise InterfaceError(
                    "Invalid connection property setting. access_key_id is required when secret_access_key is "
                    "provided")
            elif session_token is not None:
                raise InterfaceError(
                    "Invalid connection property setting. access_key_id and secret_access_key are  required when "
                    "session_token is provided")

        if not all((user, host, database, port, password)):
            if (profile is None) and (access_key_id is None):
                raise InterfaceError(
                    "Invalid connection property setting. "
                    "user, password, host, database and port are required "
                    "when not using AWS credentials and AWS profile")

        if client_protocol_version not in ClientProtocolVersion.list():
            raise InterfaceError(
                "Invalid connection property setting. client_protocol_version must be in: {}"
                .format(ClientProtocolVersion.list()))

        # basic driver parameters
        info.user_name = user
        info.host = host
        info.db_name = database
        info.port = port
        info.password = password
        info.source_address = source_address
        info.unix_sock = unix_sock
        info.timeout = timeout
        info.max_prepared_statements = max_prepared_statements
        info.tcp_keepalive = tcp_keepalive
        info.application_name = application_name
        info.replication = replication
        info.client_protocol_version = client_protocol_version
        info.database_metadata_current_db_only = database_metadata_current_db_only

        # Idp parameters
        info.idp_host = idp_host
        info.db_user = db_user
        info.app_id = app_id
        info.app_name = app_name
        info.preferred_role = preferred_role
        info.principal = principal_arn
        # Regions.fromName(string) requires the string to be lower case and in this format:
        # E.g. "us-west-2"
        info.region = region
        # cluster_identifier parameter is required
        info.cluster_identifier = cluster_identifier
        info.auto_create = auto_create
        info.db_groups = db_groups
        info.force_lowercase = force_lowercase
        info.allow_db_user_override = allow_db_user_override

        if ssl_insecure is not None:
            info.sslInsecure = ssl_insecure

        # Azure specified parameters
        info.client_id = client_id
        info.idp_tenant = idp_tenant
        info.client_secret = client_secret

        # Browser idp parameters
        info.idp_response_timeout = idp_response_timeout
        info.listen_port = listen_port
        info.login_url = login_url
        info.partner_sp_id = partner_sp_id

        # Jwt idp parameters
        info.web_identity_token = web_identity_token
        info.role_session_name = role_session_name
        info.role_arn = role_arn

        if info.iam is True:
            IamHelper.set_iam_credentials(info)
        else:
            return