Tutoriel sur la sécurisation des services Cloud Run

Ce tutoriel vous explique comment créer deux applications de service sécurisées exécutées sur Cloud Run. Cette application est un éditeur Markdown qui inclut un service "frontend" public permettant à tout le monde de rédiger du texte Markdown et un service "backend" privé qui convertit le texte Markdown au format HTML.

Schéma illustrant le flux de requêtes entre l'éditeur
Le moteur de rendu "backend" est un service privé. Cela permet de garantir une norme de transformation du texte au sein d'une organisation sans suivre les modifications dans les différentes bibliothèques en plusieurs langages.

Le service backend est privé et utilise la fonctionnalité Authentification de service à service basée sur IAM intégrée de Cloud Run (entièrement géré), qui limite l'accès au service. Les deux services sont conçus avec le principe du moindre privilège, sans accès au reste de Google Cloud, sauf si nécessaire.

Vous pouvez utiliser ce tutoriel avec Cloud Run (entièrement géré).

Objectifs

  • Créer un compte de service dédié avec des autorisations minimales pour l'authentification de service à service et l'accès au service pour le reste de Google Cloud.
  • Rédiger, créer et déployer deux services sur Cloud Run qui interagissent.
  • Effectuer des requêtes entre un service Cloud Run public et un service privé.

Coûts

Ce tutoriel utilise des composants facturables de Cloud Platform, dont :

Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût.

Les nouveaux utilisateurs de Cloud Platform peuvent bénéficier d'un essai gratuit.

Avant de commencer

  1. Connectez-vous à votre compte Google.

    Si vous n'en possédez pas déjà un, vous devez en créer un.

  2. Dans Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Cloud.

    Accéder à la page de sélection du projet

  3. Vérifiez que la facturation est activée pour votre projet Google Cloud. Découvrez comment vérifier que la facturation est activée pour votre projet.

  4. Activer l'APICloud Run

    Activer l'API

  5. Installez et initialisez le SDK Cloud.
  6. Installez curl pour tester le service

Configurer les paramètres par défaut de gcloud

Pour configurer gcloud avec les valeurs par défaut pour votre service Cloud Run, procédez comme suit :

  1. Définissez le projet par défaut :

        gcloud config set project PROJECT-ID

    Remplacez PROJECT-ID par le nom du projet que vous avez créé pour ce tutoriel.

  2. Si vous utilisez Cloud Run (entièrement géré), configurez gcloud pour la région choisie :

        gcloud config set run/region REGION

    Remplacez REGION par la région Cloud Run compatible de votre choix.

Emplacements Cloud Run

Cloud Run est régional, ce qui signifie que l'infrastructure qui exécute vos services Cloud Run est située dans une région spécifique, et gérée par Google pour être disponible de manière redondante dans toutes les zones de cette région.

Lors de la sélection de la région dans laquelle exécuter vos services Cloud Run, vous devez tout d'abord considérer vos exigences en termes de latence, de disponibilité et de durabilité. Vous pouvez généralement sélectionner la région la plus proche de vos utilisateurs, mais vous devez considérer l'emplacement des autres produits Google Cloud utilisés par votre service Cloud Run. L'utilisation conjointe de produits Google Cloud sur plusieurs sites peut avoir une incidence sur la latence et le coût de votre service.

Cloud Run est disponible dans les régions suivantes :

  • asia-east1 (Taïwan)
  • asia-northeast1 (Tokyo)
  • europe-north1 (Finlande)
  • europe-west1 (Belgique)
  • europe-west4 (Pays-Bas)
  • us-central1 (Iowa)
  • us-east1 (Caroline du Sud)
  • us-east4 (Virginie du Nord)
  • us-west1 (Oregon)

Si vous avez déjà créé un service Cloud Run, vous pouvez afficher la région dans le tableau de bord Cloud Run de Cloud Console.

Récupérer l'exemple de code

Pour récupérer l’exemple de code à utiliser, procédez comme suit :

  1. Clonez le dépôt de l'exemple d'application sur votre machine locale :

    Go

    git clone https://github.com/GoogleCloudPlatform/golang-samples.git

    Vous pouvez également télécharger l'exemple en tant que fichier ZIP et l'extraire.

  2. Accédez au répertoire contenant l'exemple de code de Cloud Run :

    Go

    cd golang-samples/run/markdown-preview/

Vérifier le service de rendu privé Markdown

Du point de vue de l'interface, il existe une spécification d'API simple pour le service Markdown :

  • Un point de terminaison à /
  • Requiert des requêtes POST
  • Le corps de la requête POST est sous forme de texte Markdown

Vous pouvez examiner l'ensemble du code pour des raisons de sécurité ou simplement pour en savoir plus en consultant le répertoire ./render/. Notez que le tutoriel n'explique pas le code de transformation Markdown. =

Transmettre à l'aide du service de rendu privé Markdown

Pour transmettre votre code, créez avec Cloud Build, importez dans Container Registry, puis déployez sur Cloud Run (entièrement géré) :

  1. Exécutez la commande suivante pour créer votre conteneur et publier sur Container Registry.

        gcloud builds submit --tag gcr.io/PROJECT_ID/renderer

    PROJECT_ID est votre ID de projet GCP et render est le nom que vous souhaitez attribuer à votre service.

    En cas de réussite, un message SUCCESS apparaît contenant l'ID, l'heure de création et le nom de l'image. Celle-ci est stockée dans Container Registry et peut être réutilisée au besoin.

  2. Déployer en tant que service privé avec accès restreint.

    Cloud Run (entièrement géré) fournit des fonctionnalités prêtes à l'emploi pour le contrôle des accès et lidentité du service. Le contrôle des accès fournit une couche d'authentification qui empêche les utilisateurs et d'autres services d'appeler le service. L'identité du service permet d'empêcher votre service d'accéder à d'autres ressources Google Cloud en créant un compte de service dédié avec des autorisations limitées.

    1. Créez un compte de service à utiliser comme "identité de calcul" du service de rendu. Par défaut, il ne dispose d'aucun autre droit que l'abonnement au projet.

       gcloud iam service-accounts create renderer-identity
          

      Le service de rendu Markdown ne s'intègre pas directement à autre chose dans Google Cloud. Aucune autorisation supplémentaire n'est requise.

    2. Déployez-le avec le compte de service renderer-identity et refusez l'accès non authentifié.

          gcloud run deploy renderer --image gcr.io/PROJECT_ID/renderer \
            --service-account renderer-identity \
            --no-allow-unauthenticated

      Cloud Run peut utiliser le nom de compte de service court au lieu de l'adresse e-mail complète si le compte de service fait partie du même projet.

Essayer le service de rendu privé Markdown

Les services privés ne peuvent pas être chargés directement par un navigateur Web. Utilisez plutôt curl ou un outil d'interface de requête HTTP similaire qui permet d'injecter un en-tête Authorization.

Pour envoyer du texte en gras au service et le voir convertir les astérisques Markdown en balises HTML <strong> :

  1. Obtenez l'URL à partir du résultat de déploiement.

  2. Utilisez gcloud pour dériver un jeton spécial d'identité unique de développement pour l'authentification :

    TOKEN=$(gcloud auth print-identity-token)
  3. Créez une demande curl qui transmet le texte brut Markdown en tant que paramètre de chaîne de requête avec une URL contenant une séquence d'échappement :

        curl -H "Authorization: Bearer $TOKEN" SERVICE_URL -d '**Hello Bold Text**'
  4. La réponse doit être un extrait de code HTML :

     <strong>Hello Bold Text</strong>
        

Vérifier l'intégration entre l'éditeur et les services de rendu

Le service d'édition propose une interface utilisateur de saisie de texte simple et un espace permettant d'afficher l'aperçu HTML. Avant de continuer, examinez le code récupéré précédemment en ouvrant le répertoire ./editor/.

Ensuite, explorez les quelques sections de code suivantes qui intègrent de manière sécurisée les deux services.

Go

Le service de rendu est défini en tant que structure avec une méthode permettant de créer des requêtes. Si l'option Authenticated est active, le serveur de métadonnées Google Cloud dans l'environnement Cloud Run est utilisé pour créer un jeton d'identité et l'ajouter à la requête HTTP dans le cadre d'un en-tête d'autorisation. Cette option est facultative pour que le service reste compatible avec le développement local.

import (
    	"bytes"
    	"fmt"
    	"io/ioutil"
    	"net/http"
    	"time"

    	"cloud.google.com/go/compute/metadata"
    )

    // RenderService represents our upstream render service.
    type RenderService struct {
    	// URL is the render service address.
    	URL string
    	// Authenticated determines whether identity token authentication will be used.
    	Authenticated bool
    }

    // NewRequest creates a new HTTP request with IAM ID Token credential.
    // This token is automatically handled by private Cloud Run (fully managed) and Cloud Functions.
    func (s *RenderService) NewRequest(method string) (*http.Request, error) {
    	req, err := http.NewRequest(method, s.URL, nil)
    	if err != nil {
    		return nil, fmt.Errorf("http.NewRequest: %v", err)
    	}

    	// Skip authentication if not using HTTPS, such as for local development.
    	if !s.Authenticated {
    		return req, nil
    	}

    	// Query the id_token with ?audience as the serviceURL
    	tokenURL := fmt.Sprintf("/instance/service-accounts/default/identity?audience=%s", s.URL)
    	token, err := metadata.Get(tokenURL)
    	if err != nil {
    		return req, fmt.Errorf("metadata.Get: failed to query id_token: %v", err)
    	}

    	req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))

    	return req, nil
    }
    

La méthode NewRequest peut être exploitée par une méthode plus spécifique au domaine qui ajoute la logique spécifique de la requête, y compris une erreur Sentinel pour identifier un problème dans le service de rendu plutôt que via des interactions réseau.


    var renderClient = &http.Client{Timeout: 30 * time.Second}

    // Render converts the Markdown plaintext to HTML.
    func (s *RenderService) Render(in []byte) ([]byte, error) {
    	req, err := s.NewRequest(http.MethodPost)
    	if err != nil {
    		return nil, fmt.Errorf("RenderService.NewRequest: %v", err)
    	}
    	req.Body = ioutil.NopCloser(bytes.NewReader(in))
    	defer req.Body.Close()

    	resp, err := renderClient.Do(req)
    	if err != nil {
    		return nil, fmt.Errorf("http.Client.Do: %v", err)
    	}

    	out, err := ioutil.ReadAll(resp.Body)
    	if err != nil {
    		return nil, fmt.Errorf("ioutil.ReadAll: %v", err)
    	}

    	if resp.StatusCode != http.StatusOK {
    		return out, fmt.Errorf("http.Client.Do: %s (%d): request not OK", http.StatusText(resp.StatusCode), resp.StatusCode)
    	}

    	return out, nil
    }
    

Envoi à l'aide du service d'édition public

Pour créer et déployer votre code :

  1. Exécutez la commande suivante pour créer votre conteneur et publier sur Container Registry.

        gcloud builds submit --tag gcr.io/PROJECT_ID/editor

    PROJECT_ID est votre ID de projet GCP et editor est le nom que vous souhaitez attribuer à votre service.

    En cas de réussite, un message SUCCESS apparaît contenant l'ID, l'heure de création et le nom de l'image. Celle-ci est stockée dans Container Registry et peut être réutilisée au besoin.

  2. Déployer en tant que service privé avec un accès spécial au service de rendu.

    1. Créez un compte de service à utiliser comme "identité de calcul" du service de rendu. Par défaut, il ne dispose d'aucun autre droit que l'abonnement au projet.

       gcloud iam service-accounts create editor-identity
          

      Le service d'édition n'a pas besoin d'interagir avec autre chose d'autre dans Google Cloud que le service de rendu Markdown.

    2. Accordez l'accès à l'identité de calcul editor-identity pour appeler le service de rendu Markdown. Tout service qui l'utilise comme identité de calcul disposera de ce privilège.

          gcloud run services add-iam-policy-binding renderer \
            --member serviceAccount:editor-identity@PROJECT_ID.iam.gserviceaccount.com \
            --role roles/run.invoker

      Étant donné que le rôle de demandeur est attribué dans le contexte du service de rendu, ce service est le seul service Cloud Run privé que l'éditeur peut demander.

    3. Déployez-le avec le compte de service editor-identity et autorisez l'accès public non authentifié.

          gcloud run deploy editor --image gcr.io/PROJECT_ID/editor \
            --service-account editor-identity \
            --set-env-vars EDITOR_UPSTREAM_RENDER_URL=RENDERER_SERVICE_URL
            --allow-unauthenticated

      Remplacer,

      • PROJECT_ID par l'ID de votre projet.
      • RENDERER_SERVICE_URL par l'URL fournie après le déploiement du service de rendu Markdown.
Schéma illustrant le flux des requêtes de l'utilisateur vers l'éditeur : éditeur pour obtenir un jeton du serveur de métadonnées, éditeur pour faire une requête au service de rendu, service de rendu pour renvoyer le code HTML à l'éditeur.
Le service d'interface avec editor-identity appelle le service de rendu. Les autorisations editor-identity et renderer-identity sont limitées. Par conséquent, tout piratage informatique ou toute injection de code a un accès limité aux autres ressources Google Cloud.

Essayez-le !

Pour essayer les deux applications de service complètes :

  1. Accédez dans votre navigateur à l'URL fournie par l'étape de déploiement ci-dessus.

  2. Essayez de modifier le texte Markdown sur la gauche, puis cliquez sur le bouton pour en afficher un aperçu sur la droite.

    Elle devrait se présenter comme ceci :

    Capture d'écran de l'interface utilisateur de l'éditeur Markdown

Si vous décidez de poursuivre le développement de ces services, n'oubliez pas qu'ils ont un accès limité IAM au reste de Google Cloud et qu'ils devront avoir des rôles IAM supplémentaires pour accéder à de nombreux autres services.

Nettoyer

Si vous avez créé un projet pour ce tutoriel, supprimez-le. Si vous avez utilisé un projet existant et que vous souhaitez le conserver sans apporter de modifications dans ce tutoriel, supprimez les ressources créées pour ce tutoriel.

Supprimer le projet

Le moyen le plus simple d'empêcher la facturation est de supprimer le projet que vous avez créé pour ce tutoriel.

Pour supprimer le projet :

  1. Dans Cloud Console, accédez à la page Gérer les ressources.

    Accéder à la page Gérer les ressources

  2. Dans la liste des projets, sélectionnez le projet que vous souhaitez supprimer, puis cliquez sur Supprimer.
  3. Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez sur Arrêter pour supprimer le projet.

Supprimer des ressources du tutoriel

  1. Supprimez le service Cloud Run que vous avez déployé dans ce tutoriel :

        gcloud run services delete SERVICE

    SERVICE est le nom du service que vous avez choisi.

    Vous pouvez également supprimer des services Cloud Run à partir de Google Cloud Console.

  2. Supprimez les configurations gcloud par défaut que vous avez ajoutées lors de la configuration du tutoriel.

     gcloud config unset run/region
        
  3. Supprimez la configuration du projet :

     gcloud config unset project
        
  4. Supprimez les autres ressources Google Cloud créées dans ce tutoriel :

Étape suivante