Secure client-server applications

Secure client-server applications with the client connector

This page provides a high level overview of the BeyondCorp Enterprise client connector and describes how to enable it to secure your client-server applications.

Overview

BeyondCorp Enterprise is the zero trust solution from Google Cloud that provides secure access to private applications with integrated threat and data protection. BeyondCorp Enterprise uses Chrome to provide secure access for all web-based (HTTPS) applications.

The BeyondCorp Enterprise client connector extends support to non-web applications by creating a secure connection to applications running in both Google Cloud and non-Google Cloud environments with full context and identity-aware access.

How it works

The following diagram provides a high-level architectural overview of the client connector.

BeyondCorp Enterprise client connector components

Following are the key components that make up the client connector:

Endpoint Verification and client agent: The client connector integrates with Endpoint Verification, a Chrome extension with a native lightweight agent that runs on user laptops or desktops, and reports device information. Endpoint Verification also acts as the control plane for the end user to start and stop connections to client gateways.

Client gateways: Regional, server-side components to which clients can connect. Client gateways are deployed by administrators. The gateways communicate with the BeyondCorp Enterprise enforcement system to enforce context-aware checks. The BeyondCorp Enterprise enforcement system uses Identity-Aware Proxy and Access Context Manager, a flexible BeyondCorp Enterprise zero trust policy engine.

The client connector sends traffic to your protected applications from end-user, client, devices through a secure channel, a gateway. You can connect to web and non-web applications running in Google Cloud or outside of Google Cloud. You can use Cloud VPN or Cloud Interconnect to connect to your applications that aren't in Google Cloud.

Before you begin

Before enabling the BeyondCorp Enterprise client connector, ensure that you have the following:

Enable the BeyondCorp Enterprise client connector

Set up Private Services Access

The client connector uses Private Services Access to enable connectivity between the Google-managed VPC network and the consumer VPC network. This ensures that the traffic from users is routed to the consumer VPC network.

  1. Private Services Access requires that you reserve an IP address range so that there's no IP address collisions between your VPC network and the Google-managed VPC network. Run the following command to allocate an IP range:

    gcloud compute addresses create RESERVED_RANGE \
      --network=CONSUMER_NETWORK \
      --project=CONSUMER_PROJECT \
      --prefix-length=16 \
      --purpose=VPC_PEERING \
      --global
    

    Replace the following:

    • RESERVED_RANGE: The name for the IP address range to be reserved for VPC Peering. The name can contain only lowercase letters, numbers, and hyphens.
    • CONSUMER_NETWORK: The name of your VPC network connected to the application.
    • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
  2. Create the VPC peering connection.

    gcloud services vpc-peerings connect \
      --network=CONSUMER_NETWORK \
      --project=CONSUMER_PROJECT \
      --ranges=RESERVED_RANGE \
      --service="servicenetworking.googleapis.com"
    

    Replace the following:

    • CONSUMER_NETWORK: The name of your VPC network connected to the application.
    • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
    • RESERVED_RANGE: The name of your reserved range for VPC peering.
  3. Get the details of the allocated IP range.

    gcloud compute addresses describe RESERVED_RANGE \
      --global \
      --project=CONSUMER_PROJECT
    

    Replace the following:

    • RESERVED_RANGE: The name of your reserved range for VPC peering.
    • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
  4. Use the address and prefixLength values from the output in the previous step to represent the allocated IP range in CIDR format, and then create a firewall rule.

    gcloud compute firewall-rules create "allow-peered-ingress" \
      --network=CONSUMER_NETWORK \
      --project=CONSUMER_PROJECT \
      --direction ingress \
      --action allow \
      --source-ranges={Allocated IP range in CIDR format i.e. address/prefixLength} \
      --rules=all
    

    Replace the following:

    • CONSUMER_NETWORK: The name of your VPC network connected to the application.
    • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.

    For information about configuring firewall rules, see Using firewall rules.

Set up the client connector resources

There are two types of resources that you must set up:

  • Client connector service: Defines a common configuration for a group of client gateways.
  • Client gateway: Refers to the client connector service and controls the regions where you want to manage user traffic.

At this time, only one client connector service per domain and one client gateway per region per client connector service is allowed. Additionally, you can only use the following regions to host your client connector service and gateway resources: asia-east1, europe-west1, us-east1, and us-central1.

Create the client connector service

gcloud

Run the following command.

gcloud alpha beyondcorp client-connector services create CLIENT_CONNECTOR_SERVICE_NAME \
  --project=CONSUMER_PROJECT \
  --location=SERVICE_LOCATION \
  --config-from-file=/path/to/file/config.json

where config.json is:

   {
     "ingress": {
       "config": {
         "transportProtocol": "TCP",
         "destinationRoutes": [{
           "address": "DESTINATION_ADDRESS",
           "netmask": "DESTINATION_MASK"
         }]
       }
     },
     "egress": {
       "peeredVpc": {
         "networkVpc": "projects/CONSUMER_PROJECT/global/networks/CONSUMER_NETWORK"
       }
     }
   }

Replace the following:

  • CLIENT_CONNECTOR_SERVICE_NAME: The name of your client connector service.
  • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
  • SERVICE_LOCATION: The region in which to create the client connector service. At this time, only the following regions are supported: asia-east1, europe-west1, us-east1, and us-central1.
  • DESTINATION_ADDRESS: The host address of the destination subnet hosting the application. For example, if your application uses 10.0.0.0/28, the address is 10.0.0.0.
  • DESTINATION_MASK: The network mask of the destination subnet hosting the application. For example, if your application uses 10.0.0.0/28, then the mask is 255.255.255.240.
  • CONSUMER_NETWORK: The name of your VPC network connected to the application.

API

Run the following command.

curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-d @config.json \
https://beyondcorp.googleapis.com/v1/projects/CONSUMER_PROJECT/locations/SERVICE_LOCATION/clientConnectorServices?client_connector_service_id=CLIENT_CONNECTOR_SERVICE_NAME

where config.json is:

   {
     "ingress": {
       "config": {
         "transportProtocol": "TCP",
         "destinationRoutes": [{
           "address": "DESTINATION_ADDRESS",
           "netmask": "DESTINATION_MASK"
         }]
       }
     },
     "egress": {
       "peeredVpc": {
         "networkVpc": "projects/CONSUMER_PROJECT/global/networks/CONSUMER_NETWORK"
       }
     }
   }

Replace the following:

  • DESTINATION_ADDRESS: The host address of the destination subnet hosting the application. For example, if your application uses 10.0.0.0/28, the address is 10.0.0.0.
  • DESTINATION_MASK: The network mask of the destination subnet hosting the application. For example, if your application uses 10.0.0.0/28, then the mask is 255.255.255.240.
  • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
  • CONSUMER_NETWORK: The name of your VPC network connected to the application.
  • SERVICE_LOCATION: The region in which to create the client connector service.
  • CLIENT_CONNECTOR_SERVICE_NAME: The name of your client connector service.

Verify that the client connector service was created by listing the service

gcloud

Run the following command.

gcloud alpha beyondcorp client-connector services list \
  --project=CONSUMER_PROJECT \
  --location=SERVICE_LOCATION

Replace the following:

  • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
  • SERVICE_LOCATION: The region in which to create the client connector service.

API

Run the following command:

curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://beyondcorp.googleapis.com/v1/projects/CONSUMER_PROJECT/locations/SERVICE_LOCATION/clientConnectorServices

Replace the following:

  • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
  • SERVICE_LOCATION: The region in which the client connector service is located.

Optional: Update a client connector service

gcloud

To update the display name, run the following command:

gcloud alpha beyondcorp client-connector services update CLIENT_CONNECTOR_SERVICE_NAME\
  --project=CONSUMER_PROJECT\
  --location=SERVICE_LOCATION\
  --display-name=NEW_DISPLAY_NAME

Replace the following:

  • CLIENT_CONNECTOR_SERVICE_NAME: The name of your client connector service.
  • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
  • SERVICE_LOCATION: The region in which the client connector service is located.
  • NEW_DISPLAY_NAME: The new display name of the client connector service.

API

To update the destination routes, run the following command:

curl -X PATCH \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-d @update.json \
https://beyondcorp.googleapis.com/v1/projects/CONSUMER_PROJECT/locations/SERVICE_LOCATION/clientConnectorServices/CLIENT_CONNECTOR_SERVICE_NAME?update_mask=ingress.config.destinationRoutes

Where update.json is:

{
  "ingress":{
    "config":{
      "destinationRoutes":[
        {
          "address":"NEW_DESTINATION_ADDRESS1",
          "netmask":"NEW_DESTINATION_MASK1"
        },
        {
          "address":"NEW_DESTINATION_ADDRESS2",
          "netmask":"NEW_DESTINATION_MASK2"
        }
      ]
    }
  }
}

Replace the following:

  • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
  • SERVICE_LOCATION: The region in which the client connector service is located.
  • CLIENT_CONNECTOR_SERVICE_NAME: The name of your client connector service.
  • NEW_DESTINATION_ADDRESS1, NEW_DESTINATION_ADDRESS2: The new host addresses of the destination subnets hosting the applications.
  • NEW_DESTINATION_MASK1, NEW_DESTINATION_MASK2: The new network masks for the destination subnets.

(Optional) Remove a client connector service

gcloud

Run the following command.

gcloud alpha beyondcorp client-connector services delete CLIENT_CONNECTOR_SERVICE_NAME \
  --project CONSUMER_PROJECT \
  --location SERVICE_LOCATION

Replace the following:

  • CLIENT_CONNECTOR_SERVICE_NAME: The name of your client connector service.
  • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
  • SERVICE_LOCATION: The region in which the client connector service is located.

API

Run the following command.

curl -X DELETE \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://beyondcorp.googleapis.com/v1/projects/CONSUMER_PROJECT/locations/SERVICE_LOCATION/clientConnectorServices/CLIENT_CONNECTOR_SERVICE_NAME

Replace the following:

  • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
  • SERVICE_LOCATION: The region in which the client connector service is located.
  • CLIENT_CONNECTOR_SERVICE_NAME: The name of your client connector service.

Create one or more client gateways

gcloud

  1. Create a client gateway.

    gcloud alpha beyondcorp client-connector gateways create CLIENT_GATEWAY_NAME \
      --project CONSUMER_PROJECT \
      --location GATEWAY_LOCATION \
      --client-connector-service \
      projects/CONSUMER_PROJECT/locations/SERVICE_LOCATION/clientConnectorServices/CLIENT_CONNECTOR_SERVICE_NAME
    

    Replace the following:

    • CLIENT_GATEWAY_NAME: The name of your client gateway.
    • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
    • GATEWAY_LOCATION: The region in which to create the client gateway.
    • SERVICE_LOCATION: The region in which the client connector service is located.
    • CLIENT_CONNECTOR_SERVICE_NAME: The name of your client connector service.
  2. Verify that the client gateways are up and running.

    gcloud alpha beyondcorp client-connector gateways list \
      --project CONSUMER_PROJECT \
      --location GATEWAY_LOCATION
    

    Replace the following:

    • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
    • GATEWAY_LOCATION: The region in which the client gateway is located.
  3. (Optional) Remove a client gateway.

    gcloud alpha beyondcorp client-connector gateways delete CLIENT_GATEWAY_NAME \
      --project CONSUMER_PROJECT \
      --location GATEWAY_LOCATION
    

    Replace the following:

    • CLIENT_GATEWAY_NAME: The name of your client gateway.
    • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
    • GATEWAY_LOCATION: The region in which the client gateway is located.

API

  1. Run the following command.

    curl -X POST \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    -d "{client_connector_service: \"projects/CONSUMER_PROJECT/locations/SERVICE_LOCATION/clientConnectorServices/CLIENT_CONNECTOR_SERVICE_NAME\"}" \
    https://beyondcorp.googleapis.com/v1/projects/CONSUMER_PROJECT/locations/GATEWAY_LOCATION/clientGateways?client_gateway_id=CLIENT_GATEWAY_NAME
    

    Replace the following:

    • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
    • SERVICE_LOCATION: The region in which the client connector service is located.
    • CLIENT_CONNECTOR_SERVICE_NAME: The name of your client connector service.
    • GATEWAY_LOCATION: The region in which to create the client gateway.
    • CLIENT_GATEWAY_NAME: The name of your client gateway.

    This step can take several minutes to complete.

  2. Verify that the client gateways are up and running.

    curl -X GET \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    https://beyondcorp.googleapis.com/v1/projects/CONSUMER_PROJECT/locations/GATEWAY_LOCATION/clientGateways
    

    Replace the following:

    • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
    • GATEWAY_LOCATION: The region in which the client gateway is located.
  3. (Optional) Remove a client gateway.

    curl -X DELETE \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    https://beyondcorp.googleapis.com/v1/projects/CONSUMER_PROJECT/locations/GATEWAY_LOCATION/clientGateways/CLIENT_GATEWAY_NAME
    

    Replace the following:

    • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
    • GATEWAY_LOCATION: The region in which the client connector gateway is located.
    • CLIENT_GATEWAY_NAME: The name of your client gateway.

Set up context-aware access policies

  1. Determine the Principals or create a user group. Identify the users that require access to the protected non-web applications. Alternatively, you can create a user group to simplify configuration and management.

  2. (Optional) Create an access level in Access Context Manager to define a context-aware rule, which you can use to restrict access to your application.

  3. Configure an IAM policy for the client connector service resource, and grant the principal or user group the Cloud BeyondCorp Client Connector Service User role (roles/beyondcorp.clientConnectorServiceUser) required to access the non-web apps. Optionally, you can specify an IAM condition to provision the role only when an access level is satisfied. To update the IAM policy for a resource, use the following read-modify-write pattern:

    1. Read the existing policy. The getIamPolicy() method reads the existing IAM policy for the client connector service resource into policy.json.

      curl -X GET \
      -H "Authorization: Bearer $(gcloud auth print-access-token)" \
      -H "Content-Type: application/json" \
      https://beyondcorp.googleapis.com/v1/projects/CONSUMER_PROJECT/locations/SERVICE_LOCATION/clientConnectorServices/CLIENT_CONNECTOR_SERVICE_NAME:getIamPolicy > policy.json
      

      Replace the following:

      • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
      • SERVICE_LOCATION: The region in which the client connector service is located.
      • CLIENT_CONNECTOR_SERVICE_NAME: The name of your client connector service.
    2. Edit the returned policy. Update the bindings in policy.json to include the new IAM role assignment. You can do this in a text editor or programmatically. Example:

      {
        "policy": {
          "bindings": [
            {
              "role": "roles/beyondcorp.clientConnectorServiceUser",
              "members": [
                "user:EXAMPLE_USER@EXAMPLE.COM",
                "group:EXAMPLE_GROUP@EXAMPLE.COM",
              ],
              "condition":
               {
                 "expression":
      "'accessPolicies/ORGANIZATION_NUMBER/accessLevels/ACCESS_LEVEL_NAME' in
      request.auth.access_levels",
                "title": "CONDITION_NAME"
              }
            }
          ]
        }
      }
      
    3. Write the updated policy. You can use the setIamPolicy() method to write the updated IAM policy. Example:

      curl -X POST \
      -H "Authorization: Bearer $(gcloud auth print-access-token)" \
      -H "Content-Type: application/json" \
      -d @policy.json \
      https://beyondcorp.googleapis.com/v1/projects/CONSUMER_PROJECT/locations/SERVICE_LOCATION/clientConnectorServices/CLIENT_CONNECTOR_SERVICE_NAME:setIamPolicy
      

      Replace the following:

      • CONSUMER_PROJECT: The ID of your project that hosts the CONSUMER_NETWORK.
      • SERVICE_LOCATION: The region in which the client connector service is located.
      • CLIENT_CONNECTOR_SERVICE_NAME: The name of your client connector service.

Install the client connector agent on endpoint devices (Windows or macOS)

  1. Enable the Endpoint Verification extension by following the steps in Set up Endpoint Verification on your devices.

  2. After Endpoint Verification is up and running, the Endpoint Verification extension for the updated user shows a START CONNECTION button. To access the protected non-web application, users can click the START CONNECTION button.

When a user initiates a connection for the first time, Endpoint Verification prompts the user to download and install the client connector binaries. Alternatively, you can download the client connector binaries at the following URLs:

After a connection is established, a user can access the protected resource. Users can choose to end the connection by clicking the END CONNECTION button.

Troubleshooting

If you run into problems using the client connector, the following information provides troubleshooting steps that might resolve your issue.

You can't access your application

The client connector gateway is running and the connection is successfully established, but you still can't reach your application.

Following are the most common reasons, and possible solutions, for this issue:

  • You didn't advertise the allocated IP range on Cloud VPN. If you use Cloud VPN to connect to the non-Google Cloud application, ensure that you also advertise the allocated IP range for Private Services Access to the peer router through the Border Gateway Protocol (BGP). For more information on how to do this, see Specify advertisements on a Cloud Router.

  • You specified an incorrect address and mask in destination routes. Ensure that the masked bits are zero when providing the address. For example, 10.0.10.1 is an invalid address to provide with a 255.255.255.0 (/24) network mask. The correct address is 10.0.10.0.

  • Possible IP conflicts between the allocated IP range for Private Service Access and the IP subnets used by the network hosting the application. Ensure these ranges are mutually exclusive. This issue is most often seen when the application is hosted in a non-Google Cloud network.

Audit logs

If you are an admin, you can view BeyondCorp Enterprise audit logs, including the client connector audit logs, in the Logging page of the console. For more information, see BeyondCorp Enterprise service audit logging.

If you are an end user, you can access connection logs by completing the following steps:

  1. Right-click on the Endpoint Verification extension in the browser.
  2. Click Options.
  3. Select the granularity for the log level. By default, the granularity level is set to Info.
  4. Click on Show Log.

What's next