Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.
Implementazioni personalizzate della convalida dell'integrità dei file di CloudTrail registro
Poiché CloudTrail utilizza algoritmi crittografici e funzioni hash standard del settore e disponibili apertamente, è possibile creare strumenti personalizzati per convalidare l'integrità dei file di registro. CloudTrail Quando la convalida dell'integrità dei file di log è abilitata, CloudTrail invia i file digest al tuo bucket Amazon S3. Puoi utilizzare questi file per implementare la tua soluzione di convalida personalizzata. Per ulteriori informazioni sui file digest, consulta CloudTrail struttura del file digest.
Questo argomento descrive come vengono firmati i file digest e illustra in dettaglio le procedure necessarie per implementare una soluzione che convalida i file digest e i file di log a cui fanno riferimento.
Comprendere come CloudTrail vengono firmati i file digest
CloudTrail i file digest sono firmati con firme RSA digitali. Per ogni file digest, CloudTrail effettua le seguenti operazioni:
-
Crea una stringa per la firma dei dati in base ai campi del file digest designato (descritti nella sezione successiva).
-
Recupera una chiave privata univoca per la Regione.
-
Passa l'hash SHA -256 della stringa e la chiave privata all'algoritmo di RSA firma, che produce una firma digitale.
-
Codifica il codice byte della firma in formato esadecimale.
-
Inserisce la firma digitale nella proprietà metadati
x-amz-meta-signature
dell'oggetto file digest Amazon S3.
Contenuto della stringa di firma dei dati
I seguenti CloudTrail oggetti sono inclusi nella stringa per la firma dei dati:
-
Il timestamp di fine del file digest in formato UTC esteso (ad esempio,)
2015-05-08T07:19:37Z
-
Percorso S3 del file digest corrente
-
L'hash -256 con codifica esadecimale SHA del file digest corrente
-
Firma con codifica esadecimale del precedente file digest
Il formato per calcolare questa stringa e un esempio di stringa vengono forniti più avanti in questo documento.
Fasi di implementazione della convalida personalizzata
Durante l'implementazione di una soluzione di convalida personalizzata, devi convalidare il file digest per primo e quindi i file di log a cui fa riferimento.
Convalida del file digest
Per convalidare un file digest, devi disporre della relativa firma, della chiave pubblica la cui chiave privata è stata utilizzata per firmare il file e di una stringa di firma dei dati che elaborerai personalmente.
-
Recuperare il file digest.
-
Verificare che il file digest sia stato recuperato dal relativo percorso originale.
-
Recuperare la firma con codifica esadecimale del file digest.
-
Recuperare l'impronta con codifica esadecimale della chiave pubblica la cui chiave privata è stata utilizzata per firmare il file digest.
-
Recuperate le chiavi pubbliche per l'intervallo di tempo corrispondente al file digest.
-
Tra le chiavi pubbliche recuperate scegliere la chiave pubblica con l'impronta corrispondente a quella nel file digest.
-
Utilizzando l'hash del file digest e gli altri campi del file, ricreare la stringa di firma dei dati per verificare la firma del file digest.
-
Convalida la firma inserendo l'hash SHA -256 della stringa, della chiave pubblica e della firma come parametri all'algoritmo di verifica della firma. RSA Se il risultato è true, il file digest è valido.
Convalida dei file di log
Se il file digest è valido, convalidare ciascun file di log a cui il file digest fa riferimento.
-
Per convalidare l'integrità di un file di registro, calcolate il relativo valore hash SHA -256 sul contenuto non compresso e confrontate i risultati con l'hash del file di registro registrato in formato esadecimale nel digest. Se i valori hash corrispondono, il file di log è valido.
-
Utilizzando le informazioni relative al file digest precedente incluse nel file digest corrente, convalidare in sequenza i file digest precedenti e i corrispondenti file di log.
Le seguenti sezioni descrivono in dettaglio queste fasi.
A. Recupero del file digest
Durante la fase iniziale di recupero del file digest più recente, devi assicurarsi di avere recuperato il file dalla relativa posizione originale, verificarne la firma digitale e recuperare l'impronta della chiave pubblica.
-
Utilizzando S3
GetObject
o la classe AmazonS3Client (ad esempio), ottieni il file digest più recente dal tuo bucket Amazon S3 per l'intervallo di tempo che desideri convalidare. -
Verificare che il bucket S3 e l'oggetto S3 utilizzati per recuperare il file corrispondano alla posizione del bucket S3 e a quella dell'oggetto S3 registrate nel file digest stesso.
-
Recupera quindi la firma digitale del file digest dalla proprietà metadati
x-amz-meta-signature
dell'oggetto del file digest in Amazon S3. -
Nel file digest recuperare l'impronta della chiave pubblica la cui chiave privata è stata utilizzata per firmare il file digest dal campo
digestPublicKeyFingerprint
.
B. Recupero della chiave pubblica per la convalida del file digest
Per ottenere la chiave pubblica per convalidare il file digest, puoi utilizzare il o il. AWS CLI CloudTrail API In entrambi i casi, puoi specificare un intervallo di tempo (ovvero un'ora di inizio e una di fine) per il file digest da convalidare. È possibile che vengano restituite una o più chiavi pubbliche per l'intervallo di tempo specificato. Le chiavi restituite possono avere intervalli di tempo di validità sovrapposti.
Nota
Poiché CloudTrail utilizza diverse coppie di chiavi pubblice/private per regione, ogni file digest è firmato con una chiave privata unica per la regione. Pertanto, quando convalidi un file digest da una determinata Regione, devi recuperare la relativa chiave pubblica dalla stessa Regione.
Usa il per recuperare le chiavi pubbliche AWS CLI
Per recuperare le chiavi pubbliche per i file digest utilizzando il AWS CLI, usa il comando. cloudtrail list-public-keys
Il comando ha il formato seguente:
aws cloudtrail list-public-keys [--start-time <start-time>] [--end-time <end-time>]
I parametri start-time e endtime sono UTC timestamp e sono opzionali. Se non specificata, verrà utilizzata l'ora corrente e verranno restituite la chiave o le chiavi pubbliche attualmente attive.
Risposta di esempio
La risposta sarà un elenco di JSON oggetti che rappresentano la chiave (o le chiavi) restituite:
{ "publicKeyList": [ { "ValidityStartTime": "1436317441.0", "ValidityEndTime": "1438909441.0", "Value": "MIIBCgKCAQEAn11L2YZ9h7onug2ILi1MWyHiMRsTQjfWE+pHVRLk1QjfWhirG+lpOa8NrwQ/r7Ah5bNL6HepznOU9XTDSfmmnP97mqyc7z/upfZdS/AHhYcGaz7n6Wc/RRBU6VmiPCrAUojuSk6/GjvA8iOPFsYDuBtviXarvuLPlrT9kAd4Lb+rFfR5peEgBEkhlzc5HuWO7S0y+KunqxX6jQBnXGMtxmPBPP0FylgWGNdFtks/4YSKcgqwH0YDcawP9GGGDAeCIqPWIXDLG1jOjRRzWfCmD0iJUkz8vTsn4hq/5ZxRFE7UBAUiVcGbdnDdvVfhF9C3dQiDq3k7adQIziLT0cShgQIDAQAB", "Fingerprint": "8eba5db5bea9b640d1c96a77256fe7f2" }, { "ValidityStartTime": "1434589460.0", "ValidityEndTime": "1437181460.0", "Value": "MIIBCgKCAQEApfYL2FiZhpN74LNWVUzhR+VheYhwhYm8w0n5Gf6i95ylW5kBAWKVEmnAQG7BvS5g9SMqFDQx52fW7NWV44IvfJ2xGXT+wT+DgR6ZQ+6yxskQNqV5YcXj4Aa5Zz4jJfsYjDuO2MDTZNIzNvBNzaBJ+r2WIWAJ/Xq54kyF63B6WE38vKuDE7nSd1FqQuEoNBFLPInvgggYe2Ym1Refe2z71wNcJ2kY+q0h1BSHrSM8RWuJIw7MXwF9iQncg9jYzUlNJomozQzAG5wSRfbplcCYNY40xvGd/aAmO0m+Y+XFMrKwtLCwseHPvj843qVno6x4BJN9bpWnoPo9sdsbGoiK3QIDAQAB", "Fingerprint": "8933b39ddc64d26d8e14ffbf6566fee4" }, { "ValidityStartTime": "1434589370.0", "ValidityEndTime": "1437181370.0", "Value": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqlzPJbvZJ42UdcmLfPUqXYNfOs6I8lCfao/tOs8CmzPOEdtLWugB9xoIUz78qVHdKIqxbaG4jWHfJBiOSSFBM0lt8cdVo4TnRa7oG9io5pysS6DJhBBAeXsicufsiFJR+wrUNh8RSLxL4k6G1+BhLX20tJkZ/erT97tDGBujAelqseGg3vPZbTx9SMfOLN65PdLFudLP7Gat0Z9p5jw/rjpclKfo9Bfc3heeBxWGKwBBOKnFAaN9V57pOaosCvPKmHd9bg7jsQkI9Xp22IzGLsTFJZYVA3KiTAElDMu80iFXPHEq9hKNbt9e4URFam+1utKVEiLkR2disdCmPTK0VQIDAQAB", "Fingerprint": "31e8b5433410dfb61a9dc45cc65b22ff" } ] }
Utilizzo della CloudTrail API per il recupero di chiavi pubbliche
Per recuperare le chiavi pubbliche per i file digest utilizzando CloudTrail API, passate i valori dell'ora di inizio e dell'ora di fine a. ListPublicKeys
API ListPublicKeys
APIRestituisce le chiavi pubbliche le cui chiavi private sono state utilizzate per firmare i file digest entro l'intervallo di tempo specificato. Per ogni chiave pubblica, restituisce API anche l'impronta digitale corrispondente.
ListPublicKeys
Questa sezione descrive i parametri di richiesta e gli elementi di risposta per. ListPublicKeys
API
Nota
La codifica dei campi binari per ListPublicKeys
è soggetta a modifiche.
Parametri della richiesta
Nome | Descrizione |
---|---|
StartTime
|
Facoltativamente, specifica l'inizio dell'intervallo di tempo in UTC cui cercare le chiavi pubbliche per i file CloudTrail digest. Se non StartTime è specificato, viene utilizzata l'ora corrente e viene restituita la chiave pubblica corrente. Tipo: DateTime |
EndTime
|
Facoltativamente, specifica la fine dell'intervallo di tempo in UTC cui cercare le chiavi pubbliche per i file CloudTrail digest. Se non EndTime è specificato, viene utilizzata l'ora corrente. Tipo: DateTime |
Elementi di risposta
PublicKeyList
, una matrice di oggetti PublicKey
contenenti:
Nome | Descrizione |
Value
|
Il valore della chiave pubblica DER codificata nel formato PKCS #1. Tipo: Blob |
ValidityStartTime
|
Ora di inizio della validità della chiave pubblica. Tipo: DateTime |
ValidityEndTime
|
Ora di fine della validità della chiave pubblica. Tipo: DateTime |
Fingerprint
|
Impronta della chiave pubblica. L'impronta può essere utilizzata per identificare la chiave pubblica da utilizzare per convalidare il file digest. Tipo: stringa |
C. Scelta della chiave pubblica da utilizzare per la convalida
Tra le chiavi pubbliche recuperate da list-public-keys
o ListPublicKeys
scegliere la chiave pubblica restituita con l'impronta corrispondente all'impronta registrata nel campo digestPublicKeyFingerprint
del file digest. Questa è la chiave pubblica che verrà utilizzata per convalidare il file digest.
D. Creazione di una nuova stringa di firma dei dati
Ora che disponi della firma del file digest e della chiave pubblica associata, devi calcolare la stringa di firma dei dati. Dopo aver calcolato tale stringa, si disporrà di tutte le informazioni necessarie per verificare la firma.
La stringa di firma dei dati ha il formato seguente:
Data_To_Sign_String = Digest_End_Timestamp_in_UTC_Extended_format + '\n' + Current_Digest_File_S3_Path + '\n' + Hex(Sha256(current-digest-file-content)) + '\n' + Previous_digest_signature_in_hex
Di seguito è riportato un esempio di stringa Data_To_Sign_String
.
2015-08-12T04:01:31Z amzn-s3-demo-bucket/AWSLogs/111122223333/CloudTrail-Digest/us-east-2/2015/08/12/111122223333_us-east-2_CloudTrail-Digest_us-east-2_20150812T040131Z.json.gz 4ff08d7c6ecd6eb313257e839645d20363ee3784a2328a7d76b99b53cc9bcacd 6e8540b83c3ac86a0312d971a225361d28ed0af20d70c211a2d405e32abf529a8145c2966e3bb47362383a52441545ed091fb81 d4c7c09dd152b84e79099ce7a9ec35d2b264eb92eb6e090f1e5ec5d40ec8a0729c02ff57f9e30d5343a8591638f8b794972ce15bb3063a01972 98b0aee2c1c8af74ec620261529265e83a9834ebef6054979d3e9a6767dfa6fdb4ae153436c567d6ae208f988047ccfc8e5e41f7d0121e54ed66b1b904f80fb2ce304458a2a6b91685b699434b946c52589e9438f8ebe5a0d80522b2f043b3710b87d2cda43e5c1e0db921d8d540b9ad5f6d4$31b1f4a8ef2d758424329583897339493a082bb36e782143ee5464b4e3eb4ef6
Dopo aver ricreato questa stringa, puoi convalidare il file digest.
E. Convalida del file digest
Passa l'hash SHA -256 della stringa di firma dei dati ricreata, della firma digitale e della chiave pubblica all'algoritmo di verifica della RSA firma. Se l'output è true, la firma del file digest è verificata e il file digest è valido.
F. Convalida dei file di log
Dopo aver convalidato il file digest, puoi convalidare il file di log a cui fa riferimento. Il file digest contiene gli hash SHA -256 dei file di registro. Se uno dei file di registro è stato modificato dopo la CloudTrail consegna, gli hash SHA -256 cambieranno e la firma del file digest non corrisponderà.
Di seguito è descritto come convalidare i file di log:
-
Eseguire un comando
S3 Get
sul file di log utilizzando le informazioni sulla posizione S3 nei campilogFiles.s3Bucket
elogFiles.s3Object
del file digest. -
Se l'
S3 Get
operazione ha esito positivo, esegui un'iterazione tra i file di registro elencati nell' logFiles array del file digest utilizzando i seguenti passaggi:-
Recuperate il valore hash originale del file dal campo
logFiles.hashValue
del log corrispondente nel file digest. -
Eseguire l'hashing dei contenuti non compressi del file di log con l'algoritmo di hashing specificato in
logFiles.hashAlgorithm
. -
Confrontare il valore hash generato con quello del log nel file digest. Se i valori hash corrispondono, il file di log è valido.
-
G. Convalida di file digest e file di log aggiuntivi
In ogni file digest, i seguenti campi forniscono le informazioni su posizione e firma del file digest precedente:
-
previousDigestS3Bucket
-
previousDigestS3Object
-
previousDigestSignature
Utilizzare queste informazioni per recuperare i file digest precedenti in sequenza, convalidare la firma di ciascuno di essi e i file di log a cui fanno riferimento mediante le procedure descritta nelle sezioni precedenti. L'unica differenza risiede nel fatto che, per i file digest precedenti, non devi recuperare la firma digitale dalle proprietà metadati Amazon S3 dell'oggetto file digest. La firma del file digest precedente è disponibile automaticamente nel campo previousDigestSignature
.
Puoi andare a ritroso nel tempo finché non raggiungi il file digest iniziale o fino all'interruzione della sequenza di file digest, a seconda di quale evento si verifica prima.
Convalida di file digest e file di log offline
Durante la convalida di file digest e file di log offline, in genere puoi fare riferimento alle procedure descritte nelle sezioni precedenti. Devi tuttavia tenere in considerazione i seguenti punti:
Utilizzo del file digest più recente
La firma digitale del file digest più recente (ovvero "corrente") si trova nelle proprietà metadati Amazon S3 dell'oggetto file digest. In uno scenario offline, la firma digitale del file digest corrente non sarà disponibile.
Per gestire questa situazione sono disponibili due modi:
-
Poiché la firma digitale per il file digest precedente si trova nel file digest corrente, iniziate la convalida dal file digest. next-to-last Con questo metodo il file digest più recente non può essere convalidato.
-
Come prima cosa recupera la firma del file digest corrente dalle proprietà metadati dell'oggetto del file digest e quindi memorizzala in modo sicuro offline. In questo modo il file digest corrente verrà convalidato assieme ai file precedenti nella sequenza.
Risoluzione del percorso
I campi nei file digest scaricati, ad esempio s3Object
e previousDigestS3Object
, continueranno a fare riferimento alle posizioni Amazon S3 online dei file di log e file digest. Una soluzione offline deve trovare un modo per reindirizzare queste posizioni al percorso corrente dei file di log e file digest scaricati.
Chiavi pubbliche
Per eseguire la convalida offline, tutte le chiavi pubbliche necessarie per convalidare i file di log in un determinato intervallo di tempo devono prima essere recuperate online (chiamando ListPublicKeys
, ad esempio) e quindi memorizzate in modo sicuro offline. Questo passaggio deve essere ripetuto ogni volta che si vuole convalidare altri file non compresi nell'intervallo di tempo iniziale specificato.
Esempio di frammento di codice di convalida
Il seguente frammento di esempio fornisce un codice scheletrico per la convalida dei file digest e di registro. CloudTrail Il codice di base non fa distinzione tra le modalità online/offline, ovvero si potrà a scegliere autonomamente se implementare il codice con o senza una connessione online ad AWS. L'implementazione suggerita utilizza Java Cryptography Extension (JCE)
Il frammento di codice di esempio mostra:
-
Come creare la stringa di firma dei dati utilizzata per convalidare la firma del file digest.
-
Come verificare la firma del file digest.
-
Come verificare gli hash del file di log.
-
Una struttura di codice per convalidare una sequenza di file digest.
import java.util.Arrays; import java.security.MessageDigest; import java.security.KeyFactory; import java.security.PublicKey; import java.security.Security; import java.security.Signature; import java.security.spec.X509EncodedKeySpec; import org.json.JSONObject; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.apache.commons.codec.binary.Hex; public class DigestFileValidator { public void validateDigestFile(String digestS3Bucket, String digestS3Object, String digestSignature) { // Using the Bouncy Castle provider as a JCE security provider - http://www.bouncycastle.org/ Security.addProvider(new BouncyCastleProvider()); // Load the digest file from S3 (using Amazon S3 Client) or from your local copy JSONObject digestFile = loadDigestFileInMemory(digestS3Bucket, digestS3Object); // Check that the digest file has been retrieved from its original location if (!digestFile.getString("digestS3Bucket").equals(digestS3Bucket) || !digestFile.getString("digestS3Object").equals(digestS3Object)) { System.err.println("Digest file has been moved from its original location."); } else { // Compute digest file hash MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); messageDigest.update(convertToByteArray(digestFile)); byte[] digestFileHash = messageDigest.digest(); messageDigest.reset(); // Compute the data to sign String dataToSign = String.format("%s%n%s/%s%n%s%n%s", digestFile.getString("digestEndTime"), digestFile.getString("digestS3Bucket"), digestFile.getString("digestS3Object"), // Constructing the S3 path of the digest file as part of the data to sign Hex.encodeHexString(digestFileHash), digestFile.getString("previousDigestSignature")); byte[] signatureContent = Hex.decodeHex(digestSignature); /* NOTE: To find the right public key to verify the signature, call CloudTrail ListPublicKey API to get a list of public keys, then match by the publicKeyFingerprint in the digest file. Also, the public key bytes returned from ListPublicKey API are DER encoded in PKCS#1 format: PublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, PublicKey BIT STRING } AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameters ANY DEFINED BY algorithm OPTIONAL } */ pkcs1PublicKeyBytes = getPublicKey(digestFile.getString("digestPublicKeyFingerprint"))); // Transform the PKCS#1 formatted public key to x.509 format. RSAPublicKey rsaPublicKey = RSAPublicKey.getInstance(pkcs1PublicKeyBytes); AlgorithmIdentifier rsaEncryption = new AlgorithmIdentifier(PKCSObjectIdentifiers.rsaEncryption, null); SubjectPublicKeyInfo publicKeyInfo = new SubjectPublicKeyInfo(rsaEncryption, rsaPublicKey); // Create the PublicKey object needed for the signature validation PublicKey publicKey = KeyFactory.getInstance("RSA", "BC").generatePublic(new X509EncodedKeySpec(publicKeyInfo.getEncoded())); // Verify signature Signature signature = Signature.getInstance("SHA256withRSA", "BC"); signature.initVerify(publicKey); signature.update(dataToSign.getBytes("UTF-8")); if (signature.verify(signatureContent)) { System.out.println("Digest file signature is valid, validating log files…"); for (int i = 0; i < digestFile.getJSONArray("logFiles").length(); i++) { JSONObject logFileMetadata = digestFile.getJSONArray("logFiles").getJSONObject(i); // Compute log file hash byte[] logFileContent = loadUncompressedLogFileInMemory( logFileMetadata.getString("s3Bucket"), logFileMetadata.getString("s3Object") ); messageDigest.update(logFileContent); byte[] logFileHash = messageDigest.digest(); messageDigest.reset(); // Retrieve expected hash for the log file being processed byte[] expectedHash = Hex.decodeHex(logFileMetadata.getString("hashValue")); boolean signaturesMatch = Arrays.equals(expectedHash, logFileHash); if (!signaturesMatch) { System.err.println(String.format("Log file: %s/%s hash doesn't match.\tExpected: %s Actual: %s", logFileMetadata.getString("s3Bucket"), logFileMetadata.getString("s3Object"), Hex.encodeHexString(expectedHash), Hex.encodeHexString(logFileHash))); } else { System.out.println(String.format("Log file: %s/%s hash match", logFileMetadata.getString("s3Bucket"), logFileMetadata.getString("s3Object"))); } } } else { System.err.println("Digest signature failed validation."); } System.out.println("Digest file validation completed."); if (chainValidationIsEnabled()) { // This enables the digests' chain validation validateDigestFile( digestFile.getString("previousDigestS3Bucket"), digestFile.getString("previousDigestS3Object"), digestFile.getString("previousDigestSignature")); } } } }