def smc_configuration(engine_name, public_ip, private_ip, public_network):
    session_login()
    vpn_name, tunnel_1, tunnel_2 = get_vpn(public_ip)

    network_name = f'awsnetwork-{public_network}'
    try:
        Network.create(name=network_name, ipv4_network=public_network)
    except CreateElementFailed as err:
        logging.info(err)

    l3fw_policy('transit_gw_policy')
    policy = firewall_rule('transit_gw_policy')

    add_tunnel_to_engine(engine_name, '2000', tunnel_1.get('outside_ip'),
                         tunnel_1.get('inside_ip_cidr'), 'tunnelA')
    add_tunnel_to_engine(engine_name, '2001', tunnel_2.get('outside_ip'),
                         tunnel_2.get('inside_ip_cidr'), 'tunnelB')

    try:
        remote_gateway_first = external_gateway(
            name=f'{vpn_name}-{1}',
            endpoint_name='endpoint_1',
            address=tunnel_1.get('outside_ip'),
            network_name=network_name
        )  # site-to-site vpn connection VPN ID include number at the end
    except CreateElementFailed as err:
        logging.info(err)

    try:
        remote_gateway_second = external_gateway(
            name=f'{vpn_name}-{2}',
            endpoint_name='endpoint_2',
            address=tunnel_2.get('outside_ip'),
            network_name=network_name
        )  # site-to-site vpn connection VPN ID include number at the end
    except CreateElementFailed as err:
        logging.info(err)

    bgp_elements(
        64512, vpn_name, tunnel_1.get('gateway'), tunnel_2.get('gateway'),
        engine_name
    )  # transit gateway : Amazon ASN inside ip is from tunnel of vpn - the /30

    add_dynamic_routing_antispoofing(engine_name)

    vpn_endpoint = Engine(engine_name).vpn_endpoint.get_contains(private_ip)
    vpn_endpoint.update(enabled=True)

    vpn_create_ipsec(engine_name, 2000, tunnel_1.get('pre_shared_key'),
                     vpn_name, 1, remote_gateway_first)
    vpn_create_ipsec(engine_name, 2001, tunnel_2.get('pre_shared_key'),
                     vpn_name, 2, remote_gateway_second)

    policy.upload(engine_name)

    session.logout()
def bgp_elements(aws_ASN, vgw_id, tunnel_inside_ip_1, tunnel_inside_ip_2,
                 engine_name):
    engine = Engine(engine_name)
    try:
        AutonomousSystem().create(name='aws-as',
                                  as_number=aws_ASN,
                                  comment='aws VGW ASN')
    except CreateElementFailed as err:
        logging.info(err)

    try:
        AutonomousSystem().create(name='ngfw-as',
                                  as_number=65000,
                                  comment='NGFW ASN')
    except CreateElementFailed as err:
        logging.info(err)

    try:
        ExternalBGPPeer().create(
            name=f"peer-{vgw_id}-1",
            comment="aws bgp peering element for tunnel_1",
            neighbor_as=AutonomousSystem("aws-as"),
            neighbor_ip=tunnel_inside_ip_1)
    except CreateElementFailed as err:
        logging.info(err)

    try:
        ExternalBGPPeer().create(
            name=f"peer-{vgw_id}-2",
            comment="aws bgp peering element for tunnel_2",
            neighbor_as=AutonomousSystem("aws-as"),
            neighbor_ip=tunnel_inside_ip_2)
    except CreateElementFailed as err:
        logging.info(err)

    engine.dynamic_routing.bgp.enable(
        autonomous_system=AutonomousSystem(name='ngfw-as'),
        announced_networks=[Network('Any network')])

    try:
        BGPPeering.get('ngfw-bgp-peering')
    except ElementNotFound as err:
        BGPPeering.create(name='ngfw-bgp-peering')  # ngfw-bgp-peering

    Engine(engine_name).routing.get(2000).add_bgp_peering(
        BGPPeering('ngfw-bgp-peering'), ExternalBGPPeer(f'peer-{vgw_id}-1'))
    Engine(engine_name).routing.get(2001).add_bgp_peering(
        BGPPeering('ngfw-bgp-peering'), ExternalBGPPeer(f'peer-{vgw_id}-2'))

    engine.update()
def add_dynamic_routing_antispoofing(engine_name):
    engine = Engine(engine_name)
    engine.dynamic_routing.update_antispoofing([Network('Any network')])

    engine.update()
def engine_creation(engine_name, private_ip, public_ip, protected_network,
                    router_ip, private_network):
    session.login(url=get_url(),
                  api_key=get_api_key(),
                  api_version=get_api_version(),
                  verify=pem_dir)

    profile = VPNProfile.get_or_create(name=PROFILE_NAME)
    profile.update(capabilities={
        'ike_v1': True,
        'aes128_for_ike': True,
        'aggressive_mode': False,
        'sha1_for_ike': True,
        'dh_group_2_for_ike': True,
        'pre_shared_key_for_ike': True,
        'rsa_signature_for_ike': False,
        'main_mode': True,
        'esp_for_ipsec': True,
        'aes128_for_ipsec': True,
        'sha1_for_ipsec': True,
        'sa_per_net': True,
        'pfs_dh_group_2_for_ipsec': True,
        'rsa_signature_for_ike': True,
        'vpn_client_sa_per_net': True
    },
                   sa_life_time=28800,
                   tunnel_life_time_seconds=3600,
                   hybrid_authentication_for_mobile_vpn=True,
                   trust_all_cas=True)
    # we should wait for the engine to be present
    engine = None
    while not engine:
        try:
            engine = Engine(engine_name)
        except smc.api.exceptions.ElementNotFound as e:
            print(e)
            print(engine)
            print("retrying in 3 sec")
            time.sleep(3)
    interface = engine.interface.get(0)

    # set_stream_logger(log_level=logging.DEBUG)
    for sub in interface.sub_interfaces():
        sub.data['dynamic'] = False
        sub.data['address'] = private_ip
        if 'dynamic_index' in sub.data:
            del sub.data['dynamic_index']
        sub.data['network_value'] = private_network
        sub.update()
    interface.update()

    ROUTER_NAME = "aws_default_router-{}".format(router_ip)
    if Router.objects.filter(ROUTER_NAME):
        router = Router(ROUTER_NAME)
    else:
        router = Router.create(ROUTER_NAME, router_ip)
    # update routing
    interface0 = engine.routing.get(0)
    for network in interface0:
        if network.name == 'Network (IPv4)':
            print("{} should be deleted".format(network))
            network.delete()
        if network.name == "network-{}".format(private_network):
            print("{} should be updated".format(network))
            interface0.add_static_route(gateway=router,
                                        destination=[Network('Any network')])
    # we need to add custom policy routing so advertised BGP routes are not used when
    # we source nat the traffic
    engine.data['policy_route'].append(
        dict(source=private_ip + '/32',
             destination=protected_network,
             gateway_ip=router_ip))
    engine.update()

    # print(interface0.as_tree())
    ca = engine.contact_addresses.get(0, interface_ip=private_ip)
    ca.add_contact_address(public_ip, location='Default')

    session.logout()