Guida per gli sviluppatori all'accesso verificato di Chrome

Informazioni sulla guida

L'API Chrome Verified Access consente i servizi di rete come VPN, Intranet pagine e così via per verificare crittograficamente che i loro client siano autentici e siano conformi alle norme aziendali. La maggior parte delle grandi imprese ha la necessità solo i dispositivi gestiti dall'azienda nelle reti WPA2 EAP-TLS nelle VPN e nelle pagine delle intranet con TLS reciproco. Molti account esistenti di soluzioni si basano su controlli euristici sullo stesso client che compromessi. Ciò presenta la sfida su cui si basava gli indicatori attestare lo stato legittimo del dispositivo, potrebbero essere state falsificati. Questa guida fornisce garanzie crittografiche basate sull'hardware dei identità del dispositivo e il suo stato non modificato e conforme alle norme. all'avvio, chiamata Accesso verificato.

Pubblico principale Amministratori di domini IT aziendali
Componenti tecnici ChromeOS, API Google Verified Access

Prerequisiti per l'Accesso verificato

Completa la seguente configurazione prima di implementare la procedura di Accesso verificato.

Abilita l'API

Configura un progetto nella console dell'API di Google e abilita l'API:

  1. Crea o utilizza un progetto esistente nel Console API di Google.
  2. Vai alla sezione API abilitate e servizi.
  3. Attiva l'API Chrome Verified Access.
  4. Crea una chiave API per l'applicazione seguendo la documentazione dell'API Google Cloud.

Crea un account di servizio

Affinché il servizio di rete possa accedere all'API Chrome Verified Access per verificare risposta alla sfida, crea un account di servizio e una chiave dell'account di servizio (non devi creare un nuovo progetto Cloud, puoi usare lo stesso).

Dopo aver creato la chiave dell'account di servizio, dovresti avere un account di servizio. il file della chiave privata scaricato. Questa è l'unica copia della chiave privata, quindi di conservarlo in un luogo sicuro.

Registrare un dispositivo Chromebook gestito

Devi avere una configurazione del dispositivo Chromebook gestita correttamente con Chrome per l'Accesso verificato.

  1. Il dispositivo Chromebook deve essere registrato per la gestione aziendale o scolastica.
  2. L'utente del dispositivo deve essere un utente registrato dello stesso dominio.
  3. L'estensione di Chrome per l'Accesso verificato deve essere installata sul dispositivo.
  4. I criteri sono configurati per abilitare l'Accesso verificato e inserire Chrome nella lista consentita e concedere l'accesso all'API per l'account di servizio che rappresenta il servizio di rete (vedi documentazione di assistenza della Console di amministrazione Google).

Verifica utente e dispositivo

Gli sviluppatori possono utilizzare l'Accesso verificato per la verifica dell'utente o del dispositivo oppure entrambi per una maggiore sicurezza:

  • Verifica del dispositivo: in caso di esito positivo, la verifica del dispositivo fornisce una garantire che il dispositivo Chrome sia registrato in un dominio gestito e che Sia conforme ai criteri relativi ai dispositivi in modalità di avvio verificato specificati dal dominio amministratore. Se al servizio di rete viene concessa l'autorizzazione per visualizzare il dispositivo identità (consulta la documentazione del Centro assistenza Google Admin Console), riceve anche un'email ID dispositivo che può essere utilizzato per controllare, monitorare o chiamare l'API Directory.

  • Verifica dell'utente: in caso di esito positivo, la verifica dell'utente fornisce una garanzia. che un utente di Chrome che ha eseguito l'accesso è un utente gestito, che utilizza un dispositivo registrato Sia conforme ai criteri relativi agli utenti in modalità di avvio verificato specificati dal dominio amministratore. Se al servizio di rete viene concessa l'autorizzazione dati utente aggiuntivi, otterrà anche una richiesta di firma del certificato rilasciata dall'utente (CSR sotto forma di chiave e challenge pubblica firmata o SPKAC, noto anche come formato keygen).

Come verificare utente e dispositivo

  1. Ricevi una verifica: l'estensione di Chrome sul dispositivo contatta il team verificato Accedi all'API per ottenere una verifica. La sfida è un aspetto opaco (un blob firmato da Google) che va bene per 1 minuto, il che significa che la verifica delle risposte a una richiesta di verifica (passaggio 3) non va a buon fine se viene utilizzata una verifica inattiva.

    Nel caso d'uso più semplice, l'utente avvia questo flusso facendo clic su un pulsante generata dall'estensione (questo è anche l'estensione di esempio fornita da Google ).

    var apiKey = 'YOUR_API_KEY_HERE';
    var challengeUrlString =
      'https://verifiedaccess.googleapis.com/v2/challenge:generate?key=' + apiKey;
    
    // Request challenge from URL
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open('POST', challengeUrlString, true);
    xmlhttp.send();
    xmlhttp.onreadystatechange = function() {
      if (xmlhttp.readyState == 4) {
        var challenge = xmlhttp.responseText;
        console.log('challenge: ' + challenge);
        // v2 of the API returns an encoded challenge so no further challenge processing is needed
      }
    };
    

    Sfida Codice helper per la codifica: se utilizzi la versione 1 dell'API, la sfida dovrà essere codificata.

    // This can be replaced by using a third-party library such as
    // [https://github.com/dcodeIO/ProtoBuf.js/wiki](https://github.com/dcodeIO/ProtoBuf.js/wiki)
    /**
     * encodeChallenge convert JSON challenge into base64 encoded byte array
     * @param {string} challenge JSON encoded challenge protobuf
     * @return {string} base64 encoded challenge protobuf
     */
    var encodeChallenge = function(challenge) {
      var jsonChallenge = JSON.parse(challenge);
      var challengeData = jsonChallenge.challenge.data;
      var challengeSignature = jsonChallenge.challenge.signature;
    
      var protobufBinary = protoEncodeChallenge(
          window.atob(challengeData), window.atob(challengeSignature));
    
      return window.btoa(protobufBinary);
    };
    
    /**
     * protoEncodeChallenge produce binary encoding of the challenge protobuf
     * @param {string} dataBinary binary data field
     * @param {string} signatureBinary binary signature field
     * @return {string} binary encoded challenge protobuf
     */
    var protoEncodeChallenge = function(dataBinary, signatureBinary) {
      var protoEncoded = '';
    
      // See https://developers.google.com/protocol-buffers/docs/encoding
      // for encoding details.
    
      // 0x0A (00001 010, field number 1, wire type 2 [length-delimited])
      protoEncoded += '\u000A';
    
      // encode length of the data
      protoEncoded += varintEncode(dataBinary.length);
      // add data
      protoEncoded += dataBinary;
    
      // 0x12 (00010 010, field number 2, wire type 2 [length-delimited])
      protoEncoded += '\u0012';
      // encode length of the signature
      protoEncoded += varintEncode(signatureBinary.length);
      // add signature
      protoEncoded += signatureBinary;
    
      return protoEncoded;
    };
    
    /**
     * varintEncode produce binary encoding of the integer number
     * @param {number} number integer number
     * @return {string} binary varint-encoded number
     */
    var varintEncode = function(number) {
      // This only works correctly for numbers 0 through 16383 (0x3FFF)
      if (number <= 127) {
        return String.fromCharCode(number);
      } else {
        return String.fromCharCode(128 + (number & 0x7f), number >>> 7);
      }
    };
    
  2. Genera una risposta a una richiesta: l'estensione di Chrome utilizza la sfida che ricevute nel passaggio 1 per chiamare l'API di Chrome enterprise.platformKeys. Questo genera una risposta a un challenge firmato e criptato, che l'estensione include nella richiesta di accesso che invia al servizio di rete.

    In questo passaggio, non c'è alcun tentativo di definire un protocollo che l'estensione e l'utilizzo dei servizi di rete per la comunicazione. Entrambe queste entità sono implementate da sviluppatori esterni e non ricevono indicazioni sul modo in cui interagiscono tra loro. Un un esempio sarebbe l'invio di una risposta a una challenge (codificata in URL) come stringa di query utilizzando HTTP POST o un'intestazione HTTP speciale.

    Ecco un esempio di codice per generare una risposta di verifica:

    Genera risposte alla sfida

      // Generate challenge response
      var encodedChallenge; // obtained by generate challenge API call
      try {
        if (isDeviceVerification) { // isDeviceVerification set by external logic
          chrome.enterprise.platformKeys.challengeKey(
              {
                scope: 'MACHINE',
                challenge: decodestr2ab(encodedChallenge),
              },
              ChallengeCallback);
        } else {
          chrome.enterprise.platformKeys.challengeKey(
              {
                scope: 'USER',
                challenge: decodestr2ab(encodedChallenge),
                registerKey: { 'RSA' }, // can also specify 'ECDSA'
              },
              ChallengeCallback);
        }
      } catch (error) {
        console.log('ERROR: ' + error);
      }
    

    Funzione di callback della sfida

      var ChallengeCallback = function(response) {
        if (chrome.runtime.lastError) {
          console.log(chrome.runtime.lastError.message);
        } else {
          var responseAsString = ab2base64str(response);
          console.log('resp: ' + responseAsString);
        ... // send on to network service
       };
      }
    

    Codice helper per la conversione Arraybu

      /**
       * ab2base64str convert an ArrayBuffer to base64 string
       * @param {ArrayBuffer} buf ArrayBuffer instance
       * @return {string} base64 encoded string representation
       * of the ArrayBuffer
       */
      var ab2base64str = function(buf) {
        var binary = '';
        var bytes = new Uint8Array(buf);
        var len = bytes.byteLength;
        for (var i = 0; i < len; i++) {
          binary += String.fromCharCode(bytes[i]);
        }
        return window.btoa(binary);
      }
    
      /**
       * decodestr2ab convert a base64 encoded string to ArrayBuffer
       * @param {string} str string instance
       * @return {ArrayBuffer} ArrayBuffer representation of the string
       */
      var decodestr2ab = function(str) {
        var binary_string =  window.atob(str);
        var len = binary_string.length;
        var bytes = new Uint8Array(len);
        for (var i = 0; i < len; i++)        {
            bytes[i] = binary_string.charCodeAt(i);
        }
        return bytes.buffer;
      }
    
  3. Verifica la risposta a una sfida: dopo aver ricevuto una risposta a una sfida da un dispositivo (ad esempio come estensione a un protocollo di autenticazione esistente), il servizio di rete deve chiamare l'API Verified Access per verificare il dispositivo strategia di identità e strategia di gestione dei criteri (vedi il codice di esempio di seguito). Per contrastare lo spoofing, consiglia al servizio di rete di identificare il client Includi l'identità prevista del client nella richiesta:

    • Per la verifica del dispositivo è necessario fornire il dominio del dispositivo previsto di Google. Probabilmente, si tratta di un valore hardcoded in molti casi, protegge le risorse di un particolare dominio. Se non è noto può essere dedotto dall'identità dell'utente.
    • Per la verifica dell'utente, l'indirizzo email dell'utente previsto deve essere fornito. Ci aspettiamo che il servizio di rete conosca i suoi utenti (di solito richiederebbe agli utenti di eseguire l'accesso).

    Quando viene chiamata, l'API di Google esegue una serie di controlli, ad esempio:

    • Verifica che la risposta al challenge sia prodotta da ChromeOS e non sia modificato in transito
    • Verifica che il dispositivo o l'utente sia gestito dall'azienda.
    • Verifica che l'identità del dispositivo/utente corrisponda a quanto previsto identità (se disponibile).
    • Verificare che la sfida a cui si risponde sia attuale (non più di 1 minuto).
    • Verifica che il dispositivo o l'utente sia conforme alle norme come specificato l'amministratore di dominio.
    • Verifica che al chiamante (servizio di rete) sia concessa l'autorizzazione per effettuare chiamate l'API.
    • Se al chiamante viene concessa l'autorizzazione per ottenere un dispositivo aggiuntivo o Dati utente, inclusi l'ID dispositivo o la firma del certificato dell'utente richiesta (CSR) nella risposta.

    Questo esempio utilizza la libreria gRPC

    import com.google.auth.oauth2.GoogleCredentials;
    import com.google.auth.oauth2.ServiceAccountCredentials;
    import com.google.chrome.verifiedaccess.v2.VerifiedAccessGrpc;
    import com.google.chrome.verifiedaccess.v2.VerifyChallengeResponseRequest;
    import com.google.chrome.verifiedaccess.v2.VerifyChallengeResponseResult;
    import com.google.protobuf.ByteString;
    
    import io.grpc.ClientInterceptor;
    import io.grpc.ClientInterceptors;
    import io.grpc.ManagedChannel;
    import io.grpc.auth.ClientAuthInterceptor;
    import io.grpc.netty.GrpcSslContexts;
    import io.grpc.netty.NettyChannelBuilder;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.util.Arrays;
    import java.util.concurrent.Executors;
    
    // https://cloud.google.com/storage/docs/authentication#generating-a-private-key
    private final String clientSecretFile = "PATH_TO_GENERATED_JSON_SECRET_FILE";
    
    private ManagedChannel channel;
    private VerifiedAccessGrpc.VerifiedAccessBlockingStub client;
    
    void setup() {
    
       channel = NettyChannelBuilder.forAddress("verifiedaccess.googleapis.com", 443)
          .sslContext(GrpcSslContexts.forClient().ciphers(null).build())
          .build();
    
       List<ClientInterceptor> interceptors = Lists.newArrayList();
       // Attach a credential for my service account and scope it for the API.
       GoogleCredentials credentials =
           ServiceAccountCredentials.class.cast(
               GoogleCredentials.fromStream(
                   new FileInputStream(new File(clientSecretFile))));
      credentials = credentials.createScoped(
          Arrays.<String>asList("https://www.googleapis.com/auth/verifiedaccess"));
      interceptors.add(
           new ClientAuthInterceptor(credentials, Executors.newSingleThreadExecutor()));
    
      // Create a stub bound to the channel with the interceptors applied
      client = VerifiedAccessGrpc.newBlockingStub(
          ClientInterceptors.intercept(channel, interceptors));
    }
    
    /**
     * Invokes the synchronous RPC call that verifies the device response.
     * Returns the result protobuf as a string.
     *
     * @param signedData base64 encoded signedData blob (this is a response from device)
     * @param expectedIdentity expected identity (domain name or user email)
     * @return the verification result protobuf as string
     */
    public String verifyChallengeResponse(String signedData, String expectedIdentity)
      throws IOException, io.grpc.StatusRuntimeException {
      VerifyChallengeResponseResult result =
        client.verifyChallengeResponse(newVerificationRequest(signedData,
            expectedIdentity)); // will throw StatusRuntimeException on error.
    
      return result.toString();
    }
    
    private VerifyChallengeResponseRequest newVerificationRequest(
      String signedData, String expectedIdentity) throws IOException {
      return VerifyChallengeResponseRequest.newBuilder()
        .setChallengeResponse(
            ByteString.copyFrom(BaseEncoding.base64().decode(signedData)))
        .setExpectedIdentity(expectedIdentity == null ? "" : expectedIdentity)
        .build();
    }
    
  4. Concedi l'accesso: questo passaggio è specifico anche del servizio di rete. Si tratta di un dell'implementazione suggerita (non obbligatoria). Possibili azioni:

    • Creazione di un cookie di sessione
    • Emissione di un certificato per l'utente o il dispositivo. In caso di problemi con l'utente verifica e supponendo che al servizio di rete sia stato concesso l'accesso ai dati utente aggiuntivi (tramite il criterio della Console di amministrazione Google), riceve un CSR firmato dall'utente, che può essere utilizzato per ottenere certificato rilasciato dall'autorità di certificazione. Durante l'integrazione con MicrosoftR CA, il servizio di rete potrebbe agire un intermediario e utilizzare l'interfaccia ICertRequest.

Utilizzo dei certificati client con Accesso verificato

. Utilizzo di certificati client con Accesso verificato.

In una grande organizzazione, possono essere presenti più servizi di rete (server VPN, punti di accesso Wi-Fi, firewall e diversi siti intranet) trarrebbero vantaggio da Accesso verificato. Tuttavia, la creazione della logica dei passaggi 2-4 (nella sezione precedente) in ciascuno di questi servizi di rete non possono essere pratici. Spesso, molti di questi servizi di rete hanno già la capacità richiedere certificati client come parte delle loro autenticazioni (ad esempio, EAP-TLS o pagine intranet TLS reciproche). Quindi se il certificato Enterprise L'autorità che emette questi certificati client potrebbe implementare i passaggi 2-4 e condizionare l'emissione del certificato client nella risposta alla sfida verifica, il possesso del certificato potrebbe essere la prova che il cliente sia spontaneo e conforme alla politica aziendale. Successivamente, ogni Wi-Fi punto di accesso, server VPN e così via potrebbero verificare la presenza di questo certificato client anziché seguire i passaggi 2-4.

In altre parole, qui la CA (che emette il certificato client all'azienda ) assume il ruolo di servizio di rete nella Figura 1. Deve richiamare l'API Verified Access e solo al momento della verifica della risposta alla richiesta di verifica sia passato, fornisci il certificato al client. Fornendo il certificato a il client equivale al Passaggio 4 - Concedi l'accesso nella Figura 1.

Viene descritto il processo per ottenere in modo sicuro certificati client sui Chromebook in questo articolo. Se la progettazione descritta in questo paragrafo, quindi Estensione di Accesso verificato e l'estensione di onboarding dei certificati client possono essere combinate in un'unica. Scopri di più su come scrivere un'estensione di onboarding dei certificati client.