Secure Memorystore access

Apps Operator Apps Operator Duration: 10 min | Persona: Apps Operator

In this section, you will secure the access by TLS to the Memorystore (Redis) instance from the OnlineBoutique’s cartservice app, without updating the source code of the app, just with Istio’s capabilities.

Initialize variables:

WORK_DIR=~/
source ${WORK_DIR}acm-workshop-variables.sh
echo "export CART_MEMORYSTORE_HOST=${REDIS_NAME}.memorystore-redis.${ONLINEBOUTIQUE_NAMESPACE}" >> ${WORK_DIR}acm-workshop-variables.sh
source ${WORK_DIR}acm-workshop-variables.sh
Info

The CART_MEMORYSTORE_HOST has been built in order to explicitly represent the Memorystore (Redis) endpoint on an Istio perspective. This name will be leveraged in 3 Istio resources: ServiceEntry, DestinationRule and Sidecar generated by the Online Boutique’s Helm chart.

Update RepoSync to deploy the Online Boutique’s Helm chart

Get Memorystore (Redis) connection information:

export REDIS_TLS_IP=$(gcloud redis instances describe $REDIS_TLS_NAME --region $GKE_LOCATION --project $TENANT_PROJECT_ID --format='get(host)')
export REDIS_TLS_PORT=$(gcloud redis instances describe $REDIS_TLS_NAME --region $GKE_LOCATION --project $TENANT_PROJECT_ID --format='get(port)')
export REDIS_TLS_CERT=$(gcloud redis instances describe $REDIS_TLS_NAME --region $GKE_LOCATION --project $TENANT_PROJECT_ID --format 'get(serverCaCerts[0].cert)')

Define the RepoSync to deploy the Online Boutique’s Helm chart with the cartservice pointing to the Memorystore (Redis) database:

cat <<EOF > ${WORK_DIR}$GKE_CONFIGS_DIR_NAME/repo-syncs/$ONLINEBOUTIQUE_NAMESPACE/repo-sync.yaml
apiVersion: configsync.gke.io/v1beta1
kind: RepoSync
metadata:
  name: repo-sync
  namespace: ${ONLINEBOUTIQUE_NAMESPACE}
spec:
  sourceFormat: unstructured
  sourceType: helm
  helm:
    repo: oci://${CHART_REGISTRY_REPOSITORY}
    chart: ${ONLINEBOUTIQUE_NAMESPACE}
    version: ${ONLINE_BOUTIQUE_VERSION:1}
    releaseName: ${ONLINEBOUTIQUE_NAMESPACE}
    auth: gcpserviceaccount
    gcpServiceAccountEmail: ${HELM_CHARTS_READER_GSA}@${TENANT_PROJECT_ID}.iam.gserviceaccount.com
    values:
      cartDatabase:
        inClusterRedis:
          create: false
        connectionString: ${REDIS_TLS_IP}:${REDIS_TLS_PORT}
        externalRedisTlsOrigination:
          enable: true
          certificate: |
$(echo -e "${REDIS_TLS_CERT}" | sed 's/^/            /')
          endpointAddress: ${REDIS_TLS_IP}
          endpointPort: ${REDIS_TLS_PORT}
      images:
        repository: ${PRIVATE_ONLINE_BOUTIQUE_REGISTRY}
        tag: ${ONLINE_BOUTIQUE_VERSION}
      nativeGrpcHealthCheck: true
      seccompProfile:
        enable: true
      loadGenerator:
        checkFrontendInitContainer: false
      frontend:
        externalService: false
        virtualService:
          create: true
          gateway:
            name: ${INGRESS_GATEWAY_NAME}
            namespace: ${INGRESS_GATEWAY_NAMESPACE}
            labelKey: asm
            labelValue: ingressgateway
          hosts:
          - ${ONLINE_BOUTIQUE_INGRESS_GATEWAY_HOST_NAME}
      serviceAccounts:
        create: true
      authorizationPolicies:
        create: true
      networkPolicies:
        create: true
      sidecars:
        create: true
EOF
Info

This will change the REDIS_ADDR environment variable of the cartservice to point to the Memorystore (Redis) database as well as removing the Deployment and the Service of the default in-cluster redis database. Also, in order to properly set up the Istio origination, this Helm chart will generate multiple resources: a ServiceEntry to register the Memorystore (Redis) instance in the Mesh as an external endpoint with its private IP address and port; a DestinationRule to configure the outgoing connections to this Memorystore (Redis) instance with TLS in SIMPLE mode (not MUTUAL) with its associated Certificate Authority and finally will annotate the cartservice Deployment to mount the certificate as a Secret via its sidecar proxy.

Note

The certificate value is in clear text in this RepoSync manifest in the Git repository. It is not a good practice, you shouldn’t do that for your own scenario. In the future, this will be fixed in this workshop with for example the use of the Google Secret Manager provider for the Secret Store CSI Driver.

Deploy Kubernetes manifests

cd ${WORK_DIR}$GKE_CONFIGS_DIR_NAME/
git add . && git commit -m "Secure Memorystore (Redis) access" && git push origin main

Check deployments

List the Kubernetes resources managed by Config Sync in GKE cluster for the Online Boutique apps repository:

Run this command and click on this link:

echo -e "https://console.cloud.google.com/kubernetes/config_management/packages?project=${TENANT_PROJECT_ID}"

Wait until you see the Sync status column as Synced and the Reconcile status column as Current.

Run this command:

gcloud alpha anthos config sync repo describe \
    --project $TENANT_PROJECT_ID \
    --managed-resources all \
    --sync-name repo-sync \
    --sync-namespace $ONLINEBOUTIQUE_NAMESPACE

Wait and re-run this command above until you see "status": "SYNCED".

List the GitHub runs for the GKE cluster configs repository:

cd ${WORK_DIR}$GKE_CONFIGS_DIR_NAME && gh run list

Check the Online Boutique website

Navigate to the Online Boutique website, click on the link displayed by the command below:

echo -e "https://${ONLINE_BOUTIQUE_INGRESS_GATEWAY_HOST_NAME}"

You should still have the Online Boutique website working successfully, but now linked to an external redis database with encryption in-transit between this Memorystore (Redis) database and the cartservice.