Anleitung zur Endnutzerauthentifizierung für Cloud Run

In dieser Anleitung wird beschrieben, wie Sie eine Webanwendung in Cloud Run erstellen, wobei der Zugriff auf angemeldete Nutzer beschränkt ist und Daten in PostgreSQL gespeichert werden. Das Einbinden der Identity Platform ermöglicht die Endnutzerauthentifizierung und bietet Nutzer-ID-Tokens, sodass der Dienst zum Abfragen einer Cloud SQL-Datenbank autorisiert werden kann. Dieser Dienst hat einen öffentlichen Client, mit dem sich externe Nutzer anmelden und auf eine Abstimmungs-UI zugreifen können, um ihre Stimmen abzugeben.

Der Einfachheit halber wird in dieser Anleitung Google als Anbieter verwendet. Nutzer müssen sich mit einem Google-Konto anmelden. Sie können jedoch für die Anmeldung der Nutzer auch andere Anbieter oder Authentifizierungsmethoden verwenden.

Mit diesem Dienst werden die Sicherheitsrisiken minimiert. Dazu werden die Dienstidentität mit der geringsten Berechtigung und Secret Manager verwendet. Dieser schützt sensible Daten, die zum Herstellen einer Verbindung zur Cloud SQL-Instanz verwendet werden.

Bei der Endnutzerauthentifizierung in diesem Beispiel:

  1. Fordert der Client für den Nutzer basierend auf Identity Platform ein signiertes ID-Token an.
  2. Wird das signierte ID-Token zusammen mit Anfragen an einen Server gesendet.
  3. Überprüft der Server die Identität des Nutzers anhand dieses signierten ID-Tokens und gewährt Zugriff auf die PostgreSQL-Datenbank von Cloud SQL.

In dieser Anleitung wird nicht die Verwendung der folgenden Authentifizierungsmethode beschrieben:

  • IAM-Authentifizierung, bei der IAM-Rollen verwendet werden, um Identitäten automatisch zu bestätigen und zu überprüfen. Dies wird für die Dienst-zu-Dienst-Authentifizierung und nicht für einzelne Identitäten empfohlen. Weitere Informationen zur Dienst-zu-Dienst-Authentifizierung finden Sie in der Anleitung zum Sichern von Cloud Run-Diensten. Die Methode zur IAM-basierten Authentifizierung kann derzeit nicht mit der ID-Token-Methode kombiniert werden.

Ziele

  • Einen Dienst in Cloud Run schreiben, erstellen und bereitstellen, mit dem folgende Aufgaben beschrieben werden:

    • Endnutzer authentifizieren, um mit der Identity Platform auf den Cloud Run-Dienst zuzugreifen.

    • Einen Cloud Run-Dienst mithilfe von Secret Manager mit einer PostgreSQL-Datenbank verbinden, um sensible Daten zu verarbeiten.

  • Eine Dienstidentität mit geringsten Berechtigungen für den minimalen Zugriff auf Google Cloud-Ressourcen erstellen.

Kosten

In dieser Anleitung werden kostenpflichtige Komponenten von Google Cloud verwendet, darunter:

Sie können mithilfe des Preisrechners eine Kostenschätzung für Ihre voraussichtliche Nutzung erstellen.

Sie sollten dieses Projekt mithilfe des Guthabens der kostenlosen Testversion durchführen können.

Neuen Cloud Platform-Nutzern steht möglicherweise eine kostenlose Testversion zur Verfügung.

Vorbereitung

  1. Melden Sie sich bei Ihrem Google Cloud-Konto an. Wenn Sie mit Google Cloud noch nicht vertraut sind, erstellen Sie ein Konto, um die Leistungsfähigkeit unserer Produkte in der Praxis sehen und bewerten zu können. Neukunden erhalten außerdem ein Guthaben von 300 $, um Arbeitslasten auszuführen, zu testen und bereitzustellen.
  2. Wählen Sie in der Google Cloud Console auf der Seite der Projektauswahl ein Google Cloud-Projekt aus oder erstellen Sie eines.

    Zur Projektauswahl

  3. Die Abrechnung für das Cloud-Projekt muss aktiviert sein. So prüfen Sie, ob die Abrechnung für Ihr Projekt aktiviert ist.

  4. Cloud Run, Secret Manager, Cloud SQL, Container Registry, and Cloud Build APIs aktivieren.

    Aktivieren Sie die APIs

  5. Installieren und initialisieren Sie das Cloud SDK.

gcloud-Standardeinstellungen einrichten

So konfigurieren Sie gcloud mit Standardeinstellungen für den Cloud Run-Dienst:

  1. Legen Sie ein Standardprojekt fest:

    gcloud config set project PROJECT_ID

    Ersetzen Sie PROJECT_ID durch den Namen des Projekts, das Sie für diese Anleitung erstellt haben.

  2. Konfigurieren Sie gcloud für die von Ihnen ausgewählte Region:

    gcloud config set run/region REGION

    Ersetzen Sie REGION durch die unterstützte Cloud Run-Region Ihrer Wahl.

Cloud Run-Standorte

Cloud Run ist regional. Die Infrastruktur, in der die Cloud Run-Dienste ausgeführt werden, befindet sich demnach in einer bestimmten Region. Aufgrund der Verwaltung durch Google sind die Anwendungen in allen Zonen innerhalb dieser Region redundant verfügbar.

Bei der Auswahl der Region, in der Ihre Cloud Run-Dienste ausgeführt werden, ist vorrangig, dass die Anforderungen hinsichtlich Latenz, Verfügbarkeit oder Langlebigkeit erfüllt werden. Sie können im Allgemeinen die Region auswählen, die Ihren Nutzern am nächsten liegt, aber Sie sollten den Standort der anderen Google Cloud-Produkte berücksichtigen, die von Ihrem Cloud Run-Dienst verwendet werden. Die gemeinsame Nutzung von Google Cloud-Produkten an mehreren Standorten kann sich auf die Latenz und die Kosten des Dienstes auswirken.

Cloud Run ist in diesen Regionen verfügbar:

Unterliegt Preisstufe 1

Unterliegt Preisstufe 2

  • asia-east2 (Hongkong)
  • asia-northeast3 (Seoul, Südkorea)
  • asia-southeast1 (Singapur)
  • asia-southeast2 (Jakarta)
  • asia-south1 (Mumbai, Indien)
  • asia-south2 (Delhi, Indien)
  • australia-southeast1 (Sydney)
  • australia-southeast2 (Melbourne)
  • europe-central2 (Warschau, Polen)
  • europe-west2 (London, Vereinigtes Königreich)
  • europe-west3 (Frankfurt, Deutschland)
  • europe-west6 (Zürich, Schweiz) Blattsymbol Niedrigster CO-Bilanz2
  • northamerica-northeast1 (Montreal) Blattsymbol Niedrigster CO-Bilanz2
  • southamerica-east1 (Sao Paulo, Brasilien) Blattsymbol Niedrigste CO2-Bilanz
  • us-west2 (Los Angeles)
  • us-west3 (Las Vegas)
  • us-west4 (Salt Lake City)

Wenn Sie bereits einen Cloud Run-Dienst erstellt haben, können Sie die Region in der Cloud Console im Cloud Run-Dashboard aufrufen.

Codebeispiel abrufen

So rufen Sie das gewünschte Codebeispiel ab:

  1. Klonen Sie das Repository der Beispiel-App auf Ihren lokalen Computer:

    Node.js

    git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git

    Sie können auch das Beispiel als ZIP-Datei herunterladen und extrahieren.

    Python

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

    Sie können auch das Beispiel als ZIP-Datei herunterladen und extrahieren.

    Java

    git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git

    Sie können auch das Beispiel als ZIP-Datei herunterladen und extrahieren.

  2. Wechseln Sie in das Verzeichnis, das den Cloud Run-Beispielcode enthält:

    Node.js

    cd nodejs-docs-samples/run/idp-sql/

    Python

    cd python-docs-samples/run/idp-sql/

    Java

    cd java-docs-samples/run/idp-sql/

Architektur visualisieren

Architekturdiagramm
Auf dem Diagramm ist die vom IdP zur Verfügung gestellte Nutzeranmeldung über ein Pop-up-Fenster für den Google Log-in zu sehen. Es erfolgt eine Weiterleitung zurück zu Cloud Run mit der Identität des Nutzers.
  1. Ein Nutzer stellt die erste Anfrage an den Dienst.

  2. Der Cloud Run-Dienst stellt dem Client ein Anmeldeformular für Nutzer bereit.

  3. Der Nutzer meldet sich über das Pop-up-Fenster für den Google Log-in an. Dieses verwendet die Identity Platform.

  4. Im Zuge der Authentifizierung wird der Nutzer zusammen mit seiner Identität zum Cloud Run-Dienst weitergeleitet.

  5. Wenn der Nutzer eine Stimme abgibt, erstellt der Client ein ID-Token und fügt es an Serveranfragen an. Der Server überprüft das ID-Token und gewährt Schreibzugriff auf Cloud SQL.

Code verstehen

In diesem Beispiel erfolgt eine Implementierung als Client und Server wie nachfolgend beschrieben.

Integration in Identity Platform: clientseitiger Code

In diesem Beispiel werden zur Integration in der Identity Platform Firebase SDKs verwendet, um Nutzer anzumelden und zu verwalten. Zum Herstellen einer Verbindung zur Identity Platform enthält das clientseitige JavaScript den Verweis auf die Anmeldedaten des Projekts als Konfigurationsobjekt und importiert die erforderlichen Firebase JavaScript SDKs:

const config = {
  apiKey: 'API_KEY',
  authDomain: 'PROJECT_ID.firebaseapp.com',
};
<!-- Firebase App (the core Firebase SDK) is always required and must be listed first-->
<script src="https://www.gstatic.com/firebasejs/7.18/firebase-app.js"></script>
<!-- Add Firebase Auth service-->
<script src="https://www.gstatic.com/firebasejs/7.18/firebase-auth.js"></script>

Das Firebase JavaScript SDK verarbeitet den Anmeldevorgang, indem Nutzer aufgefordert werden, sich mit ihrem Google-Konto anzumelden. Dazu wird ein Pop-up-Fenster geöffnet, dann erfolgt die Weiterleitung zurück zum Dienst.

function signIn() {
  const provider = new firebase.auth.GoogleAuthProvider();
  provider.addScope('https://www.googleapis.com/auth/userinfo.email');
  firebase
    .auth()
    .signInWithPopup(provider)
    .then(result => {
      // Returns the signed in user along with the provider's credential
      console.log(`${result.user.displayName} logged in.`);
      window.alert(`Welcome ${result.user.displayName}!`);
    })
    .catch(err => {
      console.log(`Error during sign in: ${err.message}`);
      window.alert('Sign in failed. Retry or check your browser logs.');
    });
}

Wenn sich ein Nutzer erfolgreich anmeldet, werden bei Firebase-Methoden ID-Tokens für die eindeutige Identifizierung und das Gewähren des Zugriffs für den Nutzer erstellt. Der Client kommuniziert mit dem Server, indem er den Header Authorization mit dem ID-Token hinzufügt.

async function vote(team) {
  if (firebase.auth().currentUser) {
    // Retrieve JWT to identify the user to the Identity Platform service.
    // Returns the current token if it has not expired. Otherwise, this will
    // refresh the token and return a new one.
    try {
      const token = await firebase.auth().currentUser.getIdToken();
      const response = await fetch('/', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          Authorization: `Bearer ${token}`,
        },
        body: 'team=' + team, // send application data (vote)
      });
      if (response.ok) {
        const text = await response.text();
        window.alert(text);
        window.location.reload();
      }
    } catch (err) {
      console.log(`Error when submitting vote: ${err}`);
      window.alert('Something went wrong... Please try again!');
    }
  } else {
    window.alert('User not signed in.');
  }
}

Integration in Identity Platform: serverseitiger Code

Der Server verwendet das Firebase Admin SDK, um die Identity Platform einzubinden und die Identität des Nutzers anhand des Nutzer-ID-Tokens zu bestätigen, das vom Client gesendet wird. Wenn das angegebene ID-Token das richtige Format hat, nicht abgelaufen ist und ordnungsgemäß signiert wurde, gibt die Methode das decodierte ID-Token zurück, das zur Extraktion der uid der Identity Platform für diesen Nutzer erforderlich ist.

Node.js

const firebase = require('firebase-admin');
// Initialize Firebase Admin SDK
firebase.initializeApp();

// Extract and verify Id Token from header
const authenticateJWT = (req, res, next) => {
  const authHeader = req.headers.authorization;
  if (authHeader) {
    const token = authHeader.split(' ')[1];
    // If the provided ID token has the correct format, is not expired, and is
    // properly signed, the method returns the decoded ID token
    firebase
      .auth()
      .verifyIdToken(token)
      .then(decodedToken => {
        const uid = decodedToken.uid;
        req.uid = uid;
        next();
      })
      .catch(err => {
        req.logger.error(`Error with authentication: ${err}`);
        return res.sendStatus(403);
      });
  } else {
    return res.sendStatus(401);
  }
};

Python

def jwt_authenticated(func: Callable[..., int]) -> Callable[..., int]:
    @wraps(func)
    def decorated_function(*args: Any, **kwargs: Any) -> Any:
        header = request.headers.get("Authorization", None)
        if header:
            token = header.split(" ")[1]
            try:
                decoded_token = firebase_admin.auth.verify_id_token(token)
            except Exception as e:
                logger.exception(e)
                return Response(status=403, response=f"Error with authentication: {e}")
        else:
            return Response(status=401)

        request.uid = decoded_token["uid"]
        return func(*args, **kwargs)

    return decorated_function

Java

/** Extract and verify Id Token from header */
private String authenticateJwt(Map<String, String> headers) {
  String authHeader =
      (headers.get("authorization") != null)
          ? headers.get("authorization")
          : headers.get("Authorization");
  if (authHeader != null) {
    String idToken = authHeader.split(" ")[1];
    // If the provided ID token has the correct format, is not expired, and is
    // properly signed, the method returns the decoded ID token
    try {
      FirebaseToken decodedToken = FirebaseAuth.getInstance().verifyIdToken(idToken);
      String uid = decodedToken.getUid();
      return uid;
    } catch (FirebaseAuthException e) {
      logger.error("Error with authentication: " + e.toString());
      throw new ResponseStatusException(HttpStatus.FORBIDDEN, "", e);
    }
  } else {
    logger.error("Error no authorization header");
    throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
  }
}

Verbindung zu Cloud SQL herstellen

Der Dienst stellt eine Verbindung zum Unix Domain Socket der Cloud SQL-Instanz her. Dazu wird folgendes Format verwendet: /cloudsql/CLOUD_SQL_CONNECTION_NAME.

Node.js

/**
 * Connect to the Cloud SQL instance through UNIX Sockets
 *
 * @param {object} credConfig The Cloud SQL connection configuration from Secret Manager
 * @returns {object} Knex's PostgreSQL client
 */
const connectWithUnixSockets = async credConfig => {
  const dbSocketPath = process.env.DB_SOCKET_PATH || '/cloudsql';
  // Establish a connection to the database
  return Knex({
    client: 'pg',
    connection: {
      user: credConfig.DB_USER, // e.g. 'my-user'
      password: credConfig.DB_PASSWORD, // e.g. 'my-user-password'
      database: credConfig.DB_NAME, // e.g. 'my-database'
      host: `${dbSocketPath}/${credConfig.CLOUD_SQL_CONNECTION_NAME}`,
    },
    ...config,
  });
};

Python

def init_unix_connection_engine(
    db_config: Dict[str, str]
) -> sqlalchemy.engine.base.Engine:
    creds = credentials.get_cred_config()
    db_user = creds["DB_USER"]
    db_pass = creds["DB_PASSWORD"]
    db_name = creds["DB_NAME"]
    db_socket_dir = creds.get("DB_SOCKET_DIR", "/cloudsql")
    cloud_sql_connection_name = creds["CLOUD_SQL_CONNECTION_NAME"]

    pool = sqlalchemy.create_engine(
        # Equivalent URL:
        # postgres+pg8000://<db_user>:<db_pass>@/<db_name>
        #                         ?unix_sock=<socket_path>/<cloud_sql_instance_name>/.s.PGSQL.5432
        sqlalchemy.engine.url.URL.create(
            drivername="postgresql+pg8000",
            username=db_user,  # e.g. "my-database-user"
            password=db_pass,  # e.g. "my-database-password"
            database=db_name,  # e.g. "my-database-name"
            query={
                "unix_sock": "{}/{}/.s.PGSQL.5432".format(
                    db_socket_dir, cloud_sql_connection_name  # e.g. "/cloudsql"
                )  # i.e "<PROJECT-NAME>:<INSTANCE-REGION>:<INSTANCE-NAME>"
            },
        ),
        **db_config,
    )
    pool.dialect.description_encoding = None
    logger.info("Database engine initialised from unix conection")

    return pool

Java

Mit der Spring Cloud Google Cloud PostgreSQL Starter-Integration können Sie mithilfe von Spring JDBC-Bibliotheken mit Ihren PostgreSQL-Datenbanken in Google Cloud SQL interagieren. Legen Sie fest, dass die Cloud SQL for MySQL-Konfiguration automatisch eine DataSource-Bean konfiguriert, die gekoppelt mit Spring JDBC ein JdbcTemplate-Objekt bereitstellt. Durch dieses werden Vorgänge wie das Abfragen und Ändern einer Datenbank ermöglicht.

# Uncomment and add env vars for local development
# spring.datasource.username=${DB_USER}
# spring.datasource.password=${DB_PASSWORD}
# spring.cloud.gcp.sql.database-name=${DB_NAME}
# spring.cloud.gcp.sql.instance-connection-name=${CLOUD_SQL_CONNECTION_NAME}  
private final JdbcTemplate jdbcTemplate;

public VoteController(JdbcTemplate jdbcTemplate) {
  this.jdbcTemplate = jdbcTemplate;
}

Mit Secret Manager vertrauliche Konfigurationen verwalten

Secret Manager ermöglicht die zentralisierte und sichere Speicherung sensibler Daten wie die Cloud SQL-Konfiguration. Der Dienst fügt zur Laufzeit die Cloud SQL-Anmeldedaten aus Secret Manager über eine Umgebungsvariable ein. Weitere Informationen zur Verwendung von Secrets mit Cloud Run.

Node.js

// CLOUD_SQL_CREDENTIALS_SECRET is the resource ID of the secret, passed in by environment variable.
// Format: projects/PROJECT_ID/secrets/SECRET_ID/versions/VERSION
const {CLOUD_SQL_CREDENTIALS_SECRET} = process.env;
if (CLOUD_SQL_CREDENTIALS_SECRET) {
  try {
    // Parse the secret that has been added as a JSON string
    // to retrieve database credentials
    return JSON.parse(CLOUD_SQL_CREDENTIALS_SECRET.toString('utf8'));
  } catch (err) {
    throw Error(
      `Unable to parse secret from Secret Manager. Make sure that the secret is JSON formatted: ${err}`
    );
  }
}

Python

def get_cred_config() -> Dict[str, str]:
    secret = os.environ.get("CLOUD_SQL_CREDENTIALS_SECRET")
    if secret:
        return json.loads(secret)

Java

/** Retrieve config from Secret Manager */
public static HashMap<String, Object> getConfig() {
  String secret = System.getenv("CLOUD_SQL_CREDENTIALS_SECRET");
  if (secret == null) {
    throw new IllegalStateException("\"CLOUD_SQL_CREDENTIALS_SECRET\" is required.");
  }
  try {
    HashMap<String, Object> config = new Gson().fromJson(secret, HashMap.class);
    return config;
  } catch (JsonSyntaxException e) {
    logger.error(
        "Unable to parse secret from Secret Manager. Make sure that it is JSON formatted: "
            + e);
    throw new RuntimeException(
        "Unable to parse secret from Secret Manager. Make sure that it is JSON formatted.");
  }
}

Dienst versenden

Identity Platform einrichten

Die Identity Platform erfordert eine manuelle Einrichtung in der Cloud Console.

  1. Rufen Sie in der Cloud Console die Seite Identity Platform Marketplace auf.

    Zur Seite „Identity Platform Marketplace“

  2. Klicken Sie auf Identity Platform aktivieren. Damit wird eine OAuth2-Client-ID mit dem Namen Web client (auto created by Google Service) erstellt.

  3. Laden Sie die generierte OAuth2-ID herunter:

    1. Rufen Sie in einem neuen Fenster die Seite „APIs & Dienste“ > „Anmeldedaten“ auf.

      Zur Seite „APIs & Dienste“ > „Anmeldedaten“

    2. Klicken Sie im Eintrag „Webclient (von Google-Dienst automatisch erstellt)“ auf das Symbol zum Herunterladen.

    3. Beachten Sie in der heruntergeladenen JSON-Ausgabe die Werte für client_id und client_secret.

  4. Konfigurieren Sie Google als Anbieter:

    1. Rufen Sie in der Cloud Console die Seite „Identitätsanbieter“ auf.

      Zur Seite "Identitätsanbieter"

    2. Klicken Sie auf Anbieter hinzufügen.

    3. Wählen Sie aus der Liste Google aus.

    4. Geben Sie in den Konfigurationseinstellungen des Web-SDK die Werte aus der JSON-Datei ein, die Sie zuvor heruntergeladen haben:

      1. Web-Client-ID: client_id

      2. Web-Clientschlüssel: client_secret

    5. Klicken Sie auf Bildschirm konfigurieren.

      1. Wählen Sie als Nutzertyp Extern aus.

      2. Füllen Sie die Pflichtfelder aus (Support-E-Mail-Adresse, Entwickler-E-Mail-Adresse).

      3. Fahren Sie fort, bis Sie die Seite Zusammenfassung erreichen.

    6. Klicken Sie unter „Anwendung konfigurieren“ auf Einrichtungsdetails. Kopieren Sie das Snippet in die static/config.js des Beispiels, um das Identity Platform Client SDK zu initialisieren.

    7. Klicken Sie auf Speichern.

Dienst bereitstellen

Führen Sie die im Folgenden aufgeführten Schritte aus, um die Bereitstellung der Infrastruktur abzuschließen, oder automatisieren den Prozess in Cloud Shell durch Klicken auf „In Google Cloud ausführen“.

In Google Cloud ausführen

  1. Erstellen Sie mithilfe der Console oder der Befehlszeile eine Cloud SQL-Instanz mit PostgreSQL-Datenbank:

    gcloud sql instances create CLOUD_SQL_INSTANCE_NAME \
        --database-version=POSTGRES_12 \
        --region=CLOUD_SQL_REGION \
        --cpu=2 \
        --memory=7680MB \
        --root-password=DB_PASSWORD
  2. Fügen Sie postgres-secrets.json die Werte Ihrer Cloud SQL-Anmeldedaten hinzu:

    Node.js

    {
      "CLOUD_SQL_CONNECTION_NAME": "PROJECT_ID:REGION:INSTANCE",
      "DB_NAME": "postgres",
      "DB_USER": "postgres",
      "DB_PASSWORD": "PASSWORD_SECRET"
    }
    

    Python

    {
      "CLOUD_SQL_CONNECTION_NAME": "PROJECT_ID:REGION:INSTANCE",
      "DB_NAME": "postgres",
      "DB_USER": "postgres",
      "DB_PASSWORD": "PASSWORD_SECRET"
    }
    

    Java

    {
      "spring.cloud.gcp.sql.instance-connection-name": "PROJECT_ID:REGION:INSTANCE",
      "spring.cloud.gcp.sql.database-name": "postgres",
      "spring.datasource.username": "postgres",
      "spring.datasource.password": "PASSWORD_SECRET"
    }

  3. Erstellen Sie mithilfe der Console oder der Befehlszeile ein versioniertes Secret:

    gcloud secrets create idp-sql-secrets \
        --replication-policy="automatic" \
        --data-file=postgres-secrets.json
  4. Erstellen Sie mithilfe der Console oder der Befehlszeile ein Dienstkonto:

    gcloud iam service-accounts create idp-sql-identity
  5. Fügen Sie mithilfe der Console oder der Befehlszeile Bindungen für den Secret Manager- und Cloud SQL-Zugriff hinzu:

    1. Gewähren Sie dem Dienstkonto Zugriff auf das erstellte Secret:

      gcloud secrets add-iam-policy-binding idp-sql-secrets \
        --member serviceAccount:idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/secretmanager.secretAccessor
    2. Gewähren Sie dem Dienstkonto Zugriff auf Cloud SQL:

      gcloud projects add-iam-policy-binding PROJECT_ID \
        --member serviceAccount:idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/cloudsql.client
  6. Erstellen Sie mithilfe von Cloud Build das Container-Image:

    Node.js

    gcloud builds submit --tag gcr.io/PROJECT_ID/idp-sql

    Python

    gcloud builds submit --tag gcr.io/PROJECT_ID/idp-sql

    Java

    In diesem Beispiel wird Jib verwendet, um Docker-Images mit gängigen Java-Tools zu erstellen. Jib optimiert Container-Builds, ohne dass ein Dockerfile erforderlich ist oder Docker installiert sein muss. Weitere Informationen zum Erstellen von Java-Containern mit Jib

    1. Verwenden Sie das gcloud Credential Helper, um Docker für das Übertragen per Push in Ihre Container Registry zu autorisieren.

      gcloud auth configure-docker

    2. Verwenden Sie das Jib-Maven-Plug-in, um den Container zu erstellen und per Push in Container Registry zu übertragen.

      mvn compile jib:build -Dimage=gcr.io/PROJECT_ID/idp-sql

  7. Stellen Sie das Container-Image mithilfe der Console oder der Befehlszeile in Cloud Run bereit:

    gcloud beta run deploy idp-sql \
        --image gcr.io/PROJECT_ID/idp-sql \
        --allow-unauthenticated \
        --service-account idp-sql-identity@PROJECT_ID.iam.gserviceaccount.com \
        --add-cloudsql-instances PROJECT_ID:REGION:CLOUD_SQL_INSTANCE_NAME \
        --update-secrets CLOUD_SQL_CREDENTIALS_SECRET=idp-sql-secrets:latest

    Verwenden Sie insbesondere die Flags --service-account, --add-cloudsql-instances und --update-secrets, um die Dienstidentität, die Cloud SQL-Instanzverbindung und den Secretnamen mit Version jeweils als Umgebungsvariable anzugeben.

Der letzte Schliff

Autorisieren Sie die URL des Cloud Run-Dienstes als zulässige Weiterleitung nach Anmeldung des Nutzers:

  1. Klicken Sie auf der Seite Identitätsanbieter auf das Stiftsymbol, um den Google-Anbieter zu bearbeiten.

  2. Klicken Sie unter „Autorisierte Domains“ auf Domain hinzufügen und geben Sie die URL des Cloud Run-Dienstes ein.

    Die Dienst-URL finden Sie nach der Erstellung oder Bereitstellung in den Logs. Alternativ können Sie sie so abrufen:

    gcloud run services describe idp-sql --format 'value(status.url)'

Testen

So testen Sie den gesamten Dienst:

  1. Rufen Sie im Browser die URL auf, die Sie im oben beschriebenen Bereitstellungsschritt erhalten haben.

  2. Klicken Sie auf die Schaltfläche Über Google anmelden und führen Sie den Authentifizierungsvorgang aus.

  3. Geben Sie Ihre Stimme ab!

    Das sollte so aussehen:

    Screenshot der Benutzeroberfläche, auf der die Anzahl der Stimmen für jedes Team und eine Liste der Stimmen zu sehen sind

Wenn Sie sich dafür entscheiden, mit der Entwicklung dieser Dienste fortzufahren, denken Sie daran, dass diese nur eingeschränkten IAM-Zugriff (Identity and Access Management) auf den Rest von Google Cloud haben und ihnen zusätzliche IAM-Rollen zugewiesen werden müssen, um auf viele andere Dienste zugreifen zu können.

Bereinigen

Wenn Sie ein neues Projekt für diese Anleitung erstellt haben, löschen Sie das Projekt. Wenn Sie ein vorhandenes Projekt verwendet haben und es beibehalten möchten, ohne die Änderungen in dieser Anleitung hinzuzufügen, löschen Sie die für die Anleitung erstellten Ressourcen.

Projekt löschen

Am einfachsten vermeiden Sie weitere Kosten, wenn Sie das zum Ausführen der Anleitung erstellte Projekt löschen.

So löschen Sie das Projekt:

  1. Wechseln Sie in der Cloud Console zur Seite Ressourcen verwalten.

    Zur Seite „Ressourcen verwalten“

  2. Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie dann auf Löschen.
  3. Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Shut down (Beenden), um das Projekt zu löschen.

Anleitungsressourcen löschen

  1. Löschen Sie den Cloud Run-Dienst, den Sie in dieser Anleitung bereitgestellt haben:

    gcloud run services delete SERVICE-NAME

    Dabei ist SERVICE-NAME der von Ihnen ausgewählte Dienstname.

    Sie können Cloud Run-Dienste auch über die Google Cloud Console löschen.

  2. Entfernen Sie die Konfiguration der Standardregion gcloud, die Sie während der Einrichtung für die Anleitung hinzugefügt haben:

     gcloud config unset run/region
    
  3. Entfernen Sie die Projektkonfiguration:

     gcloud config unset project
    
  4. Löschen Sie sonstige Google Cloud-Ressourcen, die in dieser Anleitung erstellt wurden:

Nächste Schritte