Anleitung zur Endnutzerauthentifizierung für Cloud Run


In dieser Anleitung wird gezeigt, wie Sie einen Abstimmungsdienst erstellen, der aus folgenden Elementen besteht:

  • Einem browserbasierten Client, der:

    1. Identity Platform verwendet, um ein ID-Token abzurufen.
    2. Nutzer ermöglicht, für ihre Lieblingstiere zu stimmen.
    3. Das ID-Token einer Anfrage an den Cloud Run-Server hinzufügt, der die Stimme verarbeitet.
  • Einem Cloud Run-Server, der:

    1. Prüft, ob der Endnutzer ordnungsgemäß authentifiziert wurde. Dazu wird ein gültiges ID-Token bereitgestellt.
    2. Die Stimme des Endnutzers verarbeitet.
    3. Mithilfe seiner eigenen Anmeldedaten die Stimme zur Speicherung an Cloud SQL sendet.
  • Einer PostgreSQL-Datenbank, in der die Stimmen gespeichert werden

Der Einfachheit halber wird in dieser Anleitung Google als Anbieter verwendet. Nutzer müssen sich mit einem Google-Konto authentifizieren, um ihr ID-Token zu erhalten. 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 Daten, die zur Verbindung mit der Cloud SQL-Instanz verwendet werden, mit Secret Manager geschützt. Außerdem wird eine Dienstidentität mit minimalen Berechtigungen verwendet, um den Zugriff auf die Datenbank zu sichern.

Ziele

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

  • Verwenden Sie Identity Platform, um einen Endnutzer beim Cloud Run-Dienst-Backend zu authentifizieren.

  • Erstellen Sie eine Identität mit minimalen Berechtigungen für den Dienst, um minimalen Zugriff auf Google Cloud-Ressourcen zu gewähren.

  • Verwenden Sie Secret Manager für die Verarbeitung vertraulicher Daten, wenn Sie den Cloud Run-Dienst mit einer PostgreSQL-Datenbank verbinden.

Kosten

In diesem Dokument verwenden Sie die folgenden kostenpflichtigen Komponenten von Google Cloud:

Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen. Neuen Google Cloud-Nutzern steht möglicherweise eine kostenlose Testversion zur Verfügung.

Hinweis

  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 Google Cloud-Projekt muss aktiviert sein.

  4. Wählen Sie in der Google Cloud Console auf der Seite der Projektauswahl ein Google Cloud-Projekt aus oder erstellen Sie eines.

    Zur Projektauswahl

  5. Die Abrechnung für das Google Cloud-Projekt muss aktiviert sein.

  6. Cloud Run, Secret Manager, Cloud SQL, Artifact Registry, and Cloud Build APIs aktivieren.

    Aktivieren Sie die APIs

Erforderliche Rollen

Bitten Sie Ihren Administrator, Ihnen die IAM-Rolle Inhaber (roles/owner) für Ihr Projekt zuzuweisen, um die Berechtigungen zu erhalten, die Sie zum Ausführen der Anleitung benötigen: Weitere Informationen zum Zuweisen von Rollen finden Sie unter Zugriff verwalten.

Sie können die erforderlichen Berechtigungen auch über benutzerdefinierte Rollen oder andere vordefinierte Rollen erhalten.

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

  • africa-south1 (Johannesburg)
  • 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-west10 (Berlin)
  • europe-west12 (Turin)
  • europe-west2 (London, Vereinigtes Königreich) Blattsymbol Niedriger CO2-Ausstoß
  • europe-west3 (Frankfurt, Deutschland) Blattsymbol Niedriger CO2-Wert
  • europe-west6 (Zürich, Schweiz) Blattsymbol Niedriger CO2-Ausstoß
  • me-central1 (Doha)
  • me-central2 (Dammam)
  • northamerica-northeast1 (Montreal) Blattsymbol Niedriger CO2-Ausstoß
  • northamerica-northeast2 (Toronto) Blattsymbol Niedriger CO2-Ausstoß
  • southamerica-east1 (Sao Paulo, Brasilien) Blattsymbol Niedriger CO2-Ausstoß
  • southamerica-west1 (Santiago, Chile) Blattsymbol Niedriger CO2-Ausstoß
  • us-west2 (Los Angeles)
  • us-west3 (Salt Lake City)
  • us-west4 (Las Vegas)

Wenn Sie bereits einen Cloud Run-Dienst erstellt haben, können Sie dessen Region im Cloud Run-Dashboard der Google Cloud Console 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
Im Diagramm ist die Anmeldung eines Endnutzers über ein Pop-up-Fenster für den Google Log-in zu sehen, das von der Identity Platform bereitgestellt wird. Dann erfolgt eine Zurückleitung zu Cloud Run mit der Identität des Nutzers.
  1. Ein Endnutzer stellt die erste Anfrage an den Cloud Run-Server.

  2. Der Client wird im Browser geladen.

  3. Der Nutzer stellt die Anmeldedaten über das Pop-up-Fenster für den Google Log-in von Identity Platform bereit. In einer Benachrichtigung wird der angemeldete Nutzer begrüßt.

  4. Die Steuerung wird zurück an den Server zurückgeleitet. Der Endnutzer stimmt mithilfe des Clients ab, der ein ID-Token von Identity Platform abruft und dem Abstimmungs-Anfrageheader hinzufügt.

  5. Wenn der Server die Anfrage empfängt, überprüft er das Identity Platform-ID-Token, um zu bestätigen, dass der Endnutzer ordnungsgemäß authentifiziert ist. Anschließend sendet der Server die Stimme mit seinen eigenen Anmeldedaten an Cloud SQL.

Informationen zum Kerncode

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 zu 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 der Endnutzer aufgefordert wird, sich über ein Pop-up-Fenster bei seinem Google-Konto anzumelden. Anschließend werden er zum Dienst zurückgeleitet.

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, verwendet der Client Firebase-Methoden, um ein ID-Token zu erstellen. Der Client fügt das ID-Token dem Authorization-Header seiner Anfrage an den Server hinzu.

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 das vom Client gesendete Nutzer-ID-Token zu prüfen. 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. Der Server extrahiert die Identity Platform-uid für diesen Nutzer.

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]:
    """Use the Firebase Admin SDK to parse Authorization header to verify the
    user ID token.

    The server extracts the Identity Platform uid for that user.
    """

    @wraps(func)
    def decorated_function(*args: a, **kwargs: a) -> a:
        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);
  }
}

Server mit Cloud SQL verbinden

Der Server 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, int]
) -> sqlalchemy.engine.base.Engine:
    """Initializes a Unix socket connection pool for a Cloud SQL instance of PostgreSQL.

    Args:
        db_config: a dictionary with connection pool config

    Returns:
        A SQLAlchemy Engine instance.
    """
    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": f"{db_socket_dir}/{cloud_sql_connection_name}/.s.PGSQL.5432"
                # e.g. "/cloudsql", "<PROJECT-NAME>:<INSTANCE-REGION>:<INSTANCE-NAME>"
            },
        ),
        **db_config,
    )
    pool.dialect.description_encoding = None
    logger.info("Database engine initialized from unix connection")

    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 bietet eine zentralisierte und sichere Speicherung vertraulicher Daten wie der Cloud SQL-Konfiguration. Der Server 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]:
    """Retrieve Cloud SQL credentials stored in Secret Manager
    or default to environment variables.

    Returns:
        A dictionary with Cloud SQL credential values
    """
    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.");
  }
}

Identity Platform einrichten

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.

  3. Erstellen Sie den OAuth-Zustimmungsbildschirm:

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

      Zur Seite „APIs & Dienste“ > „Anmeldedaten“

    2. Klicken Sie auf Zustimmungsbildschirm konfigurieren.

    3. Wählen Sie zu Testzwecken Extern aus.

    4. Klicken Sie auf Erstellen.

    5. Gehen Sie im Dialogfeld App-Informationen so vor:

      1. Geben Sie den Namen der Anwendung an.
      2. Wählen Sie eine der E-Mail-Adressen für den Nutzersupport aus.
      3. Geben Sie die E-Mail-Adresse ein, die Sie als Entwicklerkontakt verwenden möchten.
    6. Klicken Sie auf Speichern und fortfahren.

    7. Klicken Sie im Dialogfeld Bereiche und Testnutzer auf Speichern und fortfahren.

    8. Klicken Sie auf Zurück zum Dashboard.

    9. Klicken Sie unter Veröffentlichungsstatus auf App veröffentlichen.

    10. Klicken Sie auf Bestätigen.

  4. Erstellen Sie Ihre OAuth-Client-ID und Ihr Secret:

    1. Zur Seite „APIs & Dienste“ > „Anmeldedaten“

    2. Klicken Sie oben auf der Seite auf Anmeldedaten erstellen und wählen Sie OAuth client ID aus.

    3. Wählen Sie unter Anwendungstyp die Option Webanwendung aus und geben Sie den Namen an.

    4. Notieren Sie sich client_id und client_secret für die spätere Verwendung in diesem Verfahren.

  5. 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 Web SDK-Konfigurationseinstellungen die Werte für client_id und client_secret aus den vorherigen Schritten ein.

    5. Klicken Sie unter Anwendung konfigurieren auf Einrichtungsdetails.

    6. Kopieren Sie die Werte apiKey und authDomain in das static/config.js-Beispiel, um das SDK von Identity Platform Client 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 ein Dienstkonto für den Server mithilfe der Konsole oder der Befehlszeile:

    gcloud iam service-accounts create idp-sql-identity
  5. So gewähren Sie Rollen für den Zugriff auf Secret Manager und Cloud SQL über die Konsole oder die Befehlszeile:

    1. Erlauben Sie dem mit dem Server verknüpften Dienstkonto den 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. Erlauben Sie dem Dienstkonto, das mit dem Server verknüpft ist, den 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. Artifact Registry erstellen:

    gcloud artifacts repositories create REPOSITORY \
        --repository-format docker \
        --location REGION
    
    • REPOSITORY ist der Name des Repositorys. Repository-Namen können für jeden Repository-Speicherort in einem Projekt nur einmal vorkommen.
  7. Erstellen Sie mithilfe von Cloud Build das Container-Image:

    Node.js

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql

    Python

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/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 den gcloud Credential Helper, um Docker für das Übertragen per Push in Ihre Artifact Registry zu autorisieren.

      gcloud auth configure-docker

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

      mvn compile jib:build -Dimage=REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/idp-sql

  8. Stellen Sie das Container-Image mithilfe der Konsole oder der Befehlszeile in Cloud Run bereit: Hinweis: Der Server wird bereitgestellt, um den nicht authentifizierten Zugriff zuzulassen. Dadurch kann der Nutzer den Client laden und den Prozess starten. Der Server überprüft das ID-Token, das der Abstimmungsanfrage manuell hinzugefügt wurde, um den Endnutzer zu authentifizieren.

    gcloud run deploy idp-sql \
        --image REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/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

    Beachten Sie auch die Flags,--service-account ,--add-cloudsql-instances und--update-secrets, die die Dienstidentität, die Cloud SQL-Instanzverbindung und den Secret-Namen mit Version als Umgebungsvariable angeben.

Der letzte Schliff

Identity Platform erfordert, dass Sie die Cloud Run-Dienst-URL als zulässige Weiterleitung autorisieren, nachdem der Nutzer angemeldet wurde:

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

  2. Klicken Sie unter „Autorisierte Domains“ im rechten Bereich 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)'
  3. Zur Seite „APIs & Dienste“ > „Anmeldedaten“

    1. Klicken Sie auf das Stiftsymbol neben Ihrer OAuth-Client-ID, um sie zu bearbeiten, und dann auf die Schaltfläche Authorized redirect URIs click the URI hinzufügen.

    2. Kopieren Sie die folgende URL und fügen Sie sie in das Feld ein. Klicken Sie dann unten auf der Seite auf Speichern.

    https://PROJECT_ID.firebaseapp.com/__/auth/handler

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 Google 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