Supporto IMDSv2

Scrivo per chiedere informazioni sul supporto di IMDSv2 tramite profili di istanza in Discourse. Stiamo migrando il nostro servizio per utilizzare IMDSv2, poiché IMDSv1 non è un’opzione sicura.

Vorremmo capire se Discourse supporta attualmente IMDSv2 tramite profili di istanza e, in caso contrario, quali sono i piani per supportarlo nel prossimo futuro. Inoltre, esistono soluzioni alternative o patch disponibili che ci consentirebbero di utilizzare IMDSv2 con Discourse?

È importante per noi garantire che i nostri requisiti di sicurezza siano soddisfatti e riteniamo che l’utilizzo di credenziali temporanee tramite IMDSv2 sia un aspetto critico di tale garanzia.

Il comportamento desiderato per l’accesso alle credenziali di sicurezza fornite tramite il profilo di istanza è

  • Un’applicazione sull’istanza recupera le credenziali di sicurezza fornite dal ruolo dall’elemento di metadati dell’istanza iam/security-credentials/ nome-ruolo.
  • L’applicazione ottiene le autorizzazioni per le azioni e le risorse che abbiamo definito per il ruolo tramite le credenziali di sicurezza associate al ruolo. Queste credenziali di sicurezza sono temporanee e vengono ruotate automaticamente. Rendiamo disponibili nuove credenziali almeno cinque minuti prima della scadenza di quelle vecchie.

Abbiamo notato che ci sono differenze tra le chiamate IMDSv1 e IMDSv2.

Chiamata IMDSv1:

curl http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access

Mentre la chiamata IMDSv2 richiede l’uso di un token di metadati e può essere effettuata utilizzando i seguenti comandi:

TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \\\\\\\\\\\\\\\\\
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access

Apprezzeremmo qualsiasi informazione che possiate fornire su come possiamo utilizzare IMDSv2 con Discourse, o se esistono soluzioni alternative o patch disponibili.

Riferimento:

Non sono a conoscenza di alcun modo in cui Discourse stesso utilizzi IMDS. Hai installato Discourse su AWS in qualche modo? Stai in qualche modo utilizzando IMDSv1 con Discourse già?

Qual è il tuo caso d’uso?

Ho trovato un codice correlato.

Questo è nella specifica di test.

Discourse utilizza una versione dell’SDK AWS (3.130.2) superiore al minimo richiesto per supportare IMDSv2 e, da quanto ho potuto capire esaminando la metrica MetadataNoToken nelle nostre implementazioni AWS, non effettuiamo chiamate a IMDSv1.

Per quanto ne so, stiamo già utilizzando IMDSv2 ovunque.

3 Mi Piace

Abbiamo iniziato a usare Discourse su un’istanza AWS EC2 un anno fa. E questa settimana abbiamo aggiornato la nostra istanza per utilizzare solo IMDSv2, questo ha interrotto i nostri caricamenti AWS S3 con il messaggio di errore “impossibile firmare la richiesta senza credenziali impostate”. Utilizziamo anche l’impostazione “s3 use iam profile”.

Il servizio IMDS locale viene utilizzato da Discourse per ottenere le credenziali per effettuare altre chiamate API di servizi correlati ad AWS. Questo viene fatto utilizzando Ruby aws-sdk-s3

Stiamo riscontrando anche questo problema di backup dopo aver disabilitato IMDSv1 per motivi di sicurezza.

Possiamo vedere l’uso di IMDSv1 (in 3.3.0.beta1-dev) tramite la metrica MetadataNoToken, quindi ci stiamo chiedendo quale versione di Discourse sia passata a usare la v2 ovunque?

Anche noi siamo stati colpiti da questo oggi, una volta che abbiamo modificato la nostra istanza AWS per utilizzare solo IMDSv2: i nostri utenti non potevano più caricare immagini su S3.

Probabilmente rilevante qui: stiamo anche utilizzando l’opzione s3 use iam profile.

Per ora lo abbiamo modificato in “Opzionale”, il che significa fondamentalmente che IMDSv1 è ancora abilitato, il che non è il massimo in termini di sicurezza, ma ha fatto funzionare nuovamente i caricamenti.

1 Mi Piace

Qualcuno ha una soluzione/soluzione alternativa per far funzionare Discourse con IMDSv2?

Stiamo apportando modifiche per consentire/aspettarci che sia possibile una maggiore configurazione tramite il file .aws/config, che potrebbe sovrapporsi a questo e renderlo possibile.

@supermathie la cosa più strana che non riesco a capire è che ho configurato personalmente 2 istanze di discourse (dev/prod) che sono configurate in modo identico (upload s3 per file e backup tramite profilo IAM) e aggiornate a una versione identica (9436f5e3d4) e quando ho disabilitato IMDSv1… in dev tutto ha continuato a funzionare come previsto, mentre in prod non funziona e continua a restituire qualcosa come “impossibile firmare la richiesta senza credenziali impostate”… piuttosto sconcertante.

Se hai qualche idea su test/controlli che potrei fare, fammelo sapere.

@ducks ha identificato che i timeout nell’SDK per l’acquisizione delle credenziali IMDS sono molto aggressivi (1 secondo, nessun tentativo) quindi è possibile che stia raggiungendo quel timeout.

Ma questa è solo un’ipotesi.

Se ti connetti in console a prod, puoi farlo in modo interattivo, ad esempio:

discourse(prod)> c = Aws::S3::Client.new(region: ENV['DISCOURSE_S3_REGION'])
=> #<Aws::S3::Client>

discourse(prod)> c.list_objects_v2(bucket: ENV['DISCOURSE_S3_BUCKET']).contents.count
=> 1000
1 Mi Piace

Ho capito qual era il problema e devo solo incolpare me stesso, ma il problema era piuttosto sottile.
Il problema era con “HttpPutResponseHopLimit” impostato a 1 che non permetteva di chiamare IMDSv2 dall’interno del container

Emettendo questo comando ho ottenuto questa risposta:

> aws ec2 describe-instances --instance-ids i-00000000000000000 --query “Reservations[0].Instances[0].MetadataOptions”`
{
"State": "applied",
"HttpTokens": "optional",
"HttpPutResponseHopLimit": 1,
"HttpEndpoint": "enabled",
"HttpProtocolIpv6": "disabled",
"InstanceMetadataTags": "disabled"
}

Regolando l’impostazione l’output corretto è

> aws ec2 describe-instances --instance-ids i-00000000000000000 --query “Reservations[0].Instances[0].MetadataOptions”`
{
"State": "applied",
"HttpTokens": "required",
"HttpPutResponseHopLimit": 2,
"HttpEndpoint": "enabled",
"HttpProtocolIpv6": "disabled",
"InstanceMetadataTags": "disabled"
}

…e finalmente il mistero è risolto :sweat_smile:

Grazie a tutti per il vostro aiuto

1 Mi Piace

È fantastico saperlo!

E spero che questo si applichi anche ad altri.

Ma mi chiedo perché questo non sia un problema per noi. L’abbiamo impostato su 1 eppure funziona?

discourse(prod) > ENV['AWS_EC2_METADATA_V1_DISABLED'] = 'true'
=> "true"
discourse(prod) > c = Aws::S3::Client.new(region: ENV['DISCOURSE_S3_REGION'])
=> #<Aws::S3::Client:0x00007f9d8c0a4b00>
discourse(prod) > c.config.credentials.disable_imds_v1
=> true
discourse(prod) > c.list_objects_v2(bucket: ENV['DISCOURSE_S3_BUCKET']).contents.count
=> 1000

e quell’istanza ha questi metadati secondo lo stesso comando di query:

{
    "State": "applied",
    "HttpTokens": "optional",
    "HttpPutResponseHopLimit": 1,
    "HttpEndpoint": "enabled",
    "HttpProtocolIpv6": "disabled",
    "InstanceMetadataTags": "disabled"
}

Stiamo eseguendo Discourse in un container Docker su EC2, come altri, quindi… qual è la differenza?

Questo argomento è stato chiuso automaticamente dopo 21 ore. Non sono più consentite nuove risposte.