Question Comment savoir si une machine est une instance EC2


J'aimerais exécuter des scripts sur des hôtes qui sont des instances EC2 mais je ne sais pas comment être sûr que l'hôte est vraiment une instance EC2.

J'ai fait des tests, mais cela ne suffit pas:

  • Teste que le fichier binaire ec2_userdata est disponible (mais cela ne sera pas toujours vrai)
  • Test de disponibilité de "http://169.254.169.254/latest/meta-data"(mais sera-ce toujours vrai? et quelle est cette" adresse IP magique "?)

39
2018-01-04 09:12


origine


169.254.0.0/16 est le bloc "lien local". - Charles
C'est en fait une adresse APIPA, ce qui est assez étrange à utiliser comme référence pour un service critique comme la récupération de métadonnées. - Matthieu Cerda
Les plages d'adresses IP des EC2 sont publiques (bien que variables d'une fois à l'autre). Si vous suivez une liste en cours, vous pouvez vérifier l'IP des instances par rapport à cette plage. - Karma Fusebox
Ne comptez pas sur 169.254.169.254 si vous voulez EC2 et seulement EC2 - Des systèmes similaires à l'EC2 comme Eucalyptus le supportent également. engage.eucalyptus.com/customer/portal/articles/… - ceejayoz
Avez-vous besoin de cette méthode pour lutter contre un attaquant qui a la racine sur l'hôte et essaie de vous faire croire que c'est une instance EC2 à ses propres fins malveillantes? Si vous le faites, ce sera beaucoup plus difficile. - Mike Scott


Réponses:


En fait, il existe un moyen très simple de détecter si l'hôte est une instance EC2: vérifiez la recherche inversée de votre adresse IP publique. Les revers de l'EC2 sont assez difficiles à manquer.

De plus, si vous ne le modifiez pas, le nom d’hôte doit être votre inverse, ce qui le rend plus facile à repérer.

Vous pouvez également utiliser "l'adresse IP magique" dont vous avez parlé, car il s'agit en fait du moyen standard d'obtenir les balises d'instance EC2. Toutefois, si vous ne travaillez pas sur un réseau EC2, vous devrez attendre un délai d'expiration, ce qui n'est généralement pas le cas. souhaitable...

Si ces méthodes ne suffisent pas, il suffit de faire un whois de votre adresse IP et de vérifier si vous vous trouvez dans le bloc IP Amazon EC2.

EDIT: Vous pouvez utiliser ce petit bit shell:

#!/bin/bash
LOCAL_HOSTNAME=$(hostname -d)
if [[ ${LOCAL_HOSTNAME} =~ .*\.amazonaws\.com ]]
then
        echo "This is an EC2 instance"
else
        echo "This is not an EC2 instance, or a reverse-customized one"
fi

Attention cependant, [[est un bashisme. Vous pouvez également utiliser un Python ou Perl Uniline, YMMV.


3
2018-01-04 09:20



cela ne fonctionne pas dans un VPC ou un environnement dans lequel vous avez changé le nom d'hôte; par exemple. si vos machines sont dans domain.local - Preflightsiren
le bit du nom d'hôte est voué à l'échec. - Dan Pritts
hostname -d résultats eu-west-1.compute.internal - Bulletmagnet


Modification de la réponse de Hannes pour éviter les messages d'erreur et inclure un exemple d'utilisation dans le script:

if [ -f /sys/hypervisor/uuid ] && [ `head -c 3 /sys/hypervisor/uuid` == ec2 ]; then
    echo yes
else
    echo no
fi

Cela ne fonctionne pas dans les instances Windows. L'avantage par rapport au curl est qu'il est presque instantané sur les EC2 et les non-EC2.


37
2018-06-22 18:36



AWS semble également recommander de le faire de cette façon docs.aws.amazon.com/AWSEC2/latest/UserGuide/… - Mike
J'aime cette méthode. Sachez simplement qu’un système non EC2 fonctionnant sous un hyperviseur peut générer un UUID commençant par ec2 - un faux positif. Il est peu probable (une chance sur 256) et uniquement si vous utilisez un hyperviseur qui remplit ce fichier. C’est pourquoi la documentation liée ci-dessus indique «vous êtes Probablement regarder une instance EC2 ". - Nate
@Nate, bon point, mais cela ne devrait-il pas être une chance sur 4096? (16 x 16 x 16) - Wildcard
@Wildcard: Je ne peux pas éditer mon commentaire, mais c’est vrai. - Nate
DANGER! Cette méthode fonctionnait de manière fiable pour nous depuis des années ... jusqu’à tout récemment, avec les derniers types c5 et m5 qui ne pas avoir ce fichier présent. Je dois donc ajouter une vérification de secours de 169.254.169.254 pour gérer ces cas. - Josh Kupershmidt


Recherchez les métadonnées par le nom de domaine interne EC2 au lieu de l'adresse IP, ce qui renverra une défaillance DNS rapide si vous n'êtes pas sur EC2 et évite les conflits IP ou les problèmes de routage:

curl -s http://instance-data.ec2.internal && echo "EC2 instance!" || echo "Non EC2 instance!"

Sur certaines distributions, systèmes très basiques, ou très tôt lors des étapes d’installation boucle n'est pas disponible. En utilisant wget au lieu:

wget -q http://instance-data.ec2.internal && echo "EC2 instance!" || echo "Non EC2 instance!"

16
2018-02-13 18:41



Malheureusement, semble échouer dans VPC! - Ashe
De même, n'utilisez pas le caractère de point d'exclamation à l'intérieur des guillemets - votre peut exploser avec -bash: !": event not found. Utilisez des guillemets simples pour ceux echos à la place. - Josh Kupershmidt
cela suppose probablement que le serveur utilise toujours des serveurs DNS EC2 qui connaissent la zone ec2.internal et que personne n'a modifié /etc/resolv.conf en 8.8.8.8 ni lancé sa propre infrastructure DNS. - lamont
AWS semble avoir cassé cela. Je ne peux plus résoudre instance-data.ec2.internal. instance-data.us-west-2.compute.internal fonctionne bien, du moins pour le moment. - Bryan Larsen


Si l'objectif est de dire s'il s'agit d'une instance EC2 OU d'un autre type d'instance de cloud, comme Google, dmidecode fonctionne très bien et aucun réseau n'est requis. J'aime cette approche par rapport à d'autres approches, car le chemin d'accès aux métadonnées est différent pour EC2 et GCE.

# From a google compute VM
$ sudo dmidecode -s bios-version
Google

# From an amazon ec2 VM
$ sudo dmidecode -s bios-version
4.2.amazon

15
2018-05-05 16:02



Je m'attendrais à ce que cela fonctionne correctement dans d'autres environnements de machines virtuelles et même sur du matériel réel - je ne m'attends pas à ce que les fournisseurs de matériel envoient des systèmes dont la version du bios indique "amazon" ... - Guss


Tout d’abord, j’ai ressenti le besoin de publier une nouvelle réponse en raison des problèmes subtils suivants avec les réponses existantes et après avoir reçu une question sur mon Commentez la réponse de @ qwertzguy. Voici les problèmes avec les réponses actuelles:

  1. le réponse acceptée de @MatthieuCerda ne fonctionne certainement pas de manière fiable, du moins pas sur les instances de VPC que j'ai vérifiées. (Sur mes instances, je reçois un nom de VPC pour hostname -d, qui est utilisé pour le DNS interne, pas avec "amazonaws.com" dedans.)
  2. le réponse la plus votée de @qwertzguy ne fonctionne pas sur les nouvelles instances m5 ou c5, qui n'ont pas ce fichier. Amazon néglige de documenter ce changement de comportement autant que je sache, bien que le page de doc à ce sujet dit "... Si / sys / hypervisor / uuid existe ... ". J'ai demandé au support technique d'AWS si ce changement était intentionnel, voir ci-dessous †.
  3. le réponse de @Jer ne fonctionne pas nécessairement partout car le instance-data.ec2.internal La recherche DNS peut ne pas fonctionner. Sur une instance de VPC Ubuntu EC2 que je viens de tester, je vois: $ curl http://instance-data.ec2.internal curl: (6) Could not resolve host: instance-data.ec2.internal ce qui ferait que le code reposant sur cette méthode conclurait faussement que ce n'est pas sur EC2!
  4. le répondre à utiliser dmidecode de @tamale peut fonctionner, mais repose sur vous a.) dmidecode disponible sur votre instance, et b.) ayant la racine ou sudo capacité sans mot de passe de votre code.
  5. le répondre à vérifier / sys / devices / virtual / dmi / id / bios_version de @spkane est dangereusement trompeur! J'ai vérifié une instance Ubuntu 14.04 m5 et obtenu un bios_version de 1.0. Ce fichier n'est pas du tout documenté sur le doc d'Amazon, donc je ne compterais vraiment pas dessus.
  6. La première partie de la réponse de @ Chris-Montanaro vérifier une URL tierce non fiable et utiliser whois sur le résultat est problématique à plusieurs niveaux. Notez que l'URL suggérée dans cette réponse est une page 404 en ce moment! Même si vous trouviez un service tiers qui fonctionnait, il serait comparativement très lent (comparé à la vérification locale d'un fichier) et éventuellement à des problèmes de limitation de débit ou de réseau, ou éventuellement votre instance EC2 ne dispose même pas d'un accès réseau externe.
  7. La deuxième suggestion dans le réponse de @ Chris-Montanaro vérifier http://169.254.169.254/ C’est un peu mieux, mais un autre intervenant note que d’autres fournisseurs de cloud fournissent cette URL de métadonnées d’instance disponible. Vous devez donc faire attention à éviter les faux positifs. En outre, il sera toujours beaucoup plus lent qu'un fichier local. J'ai vu cette vérification être particulièrement lente (plusieurs secondes pour revenir) sur des instances très chargées. En outre, vous devez vous rappeler de passer un -m ou --max-time l’argument à éviter pour qu’il reste longtemps bloqué, en particulier sur une instance non EC2 où cette adresse peut ne mener nulle part et se bloquer (comme dans @ la réponse de l'algue).

En outre, je ne vois pas que quelqu'un a mentionné Amazon documenté repli de la vérification du fichier (possible) /sys/devices/virtual/dmi/id/product_uuid.

Qui savait que déterminer si vous utilisiez EC2 était si compliqué?! OK, maintenant que nous avons (la plupart) des problèmes avec les approches énumérées, voici un extrait de code suggéré pour vérifier si vous utilisez bien EC2. Je pense que cela devrait fonctionner généralement sur presque toutes les instances Linux, les instances Windows étant un exercice pour le lecteur.

#!/bin/bash

# This first, simple check will work for many older instance types.
if [ -f /sys/hypervisor/uuid ]; then
  # File should be readable by non-root users.
  if [ `head -c 3 /sys/hypervisor/uuid` == "ec2" ]; then
    echo yes
  else
    echo no
  fi

# This check will work on newer m5/c5 instances, but only if you have root!
elif [ -r /sys/devices/virtual/dmi/id/product_uuid ]; then
  # If the file exists AND is readable by us, we can rely on it.
  if [ `head -c 3 /sys/devices/virtual/dmi/id/product_uuid` == "EC2" ]; then
    echo yes
  else
    echo no
  fi

else
  # Fallback check of http://169.254.169.254/. If we wanted to be REALLY
  # authoritative, we could follow Amazon's suggestions for cryptographically
  # verifying their signature, see here:
  #    https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html
  # but this is almost certainly overkill for this purpose (and the above
  # checks of "EC2" prefixes have a higher false positive potential, anyway).
  if $(curl -s -m 5 http://169.254.169.254/latest/dynamic/instance-identity/document | grep -q availabilityZone) ; then
    echo yes
  else
    echo no
  fi

fi

De toute évidence, vous pouvez développer cela avec encore plus de contrôles de substitution et inclure la paranoïa concernant la gestion, par exemple. un faux positif de /sys/hypervisor/uuid passe à commencer par "ec2" par hasard et ainsi de suite. Mais il s’agit là d’une solution suffisante pour illustrer notre propos et probablement pour presque tous les cas d’utilisation non pathologiques.

[†] Vous avez obtenu cette explication du support AWS à propos de la modification des instances c5 / m5:

Les instances C5 et M5 utilisent un nouvelle pile d'hyperviseur et les pilotes de noyau associés ne créent pas de fichiers dans sysfs (monté sur / sys) en tant que pilotes Xen utilisé par les autres / anciens types d'instances ne. Le meilleur moyen de détecter si le système d'exploitation s'exécute sur une instance EC2 consiste à prendre en compte les différentes possibilités répertoriées dans documentation que vous avez liée.


10
2018-03-20 14:46



Oui compagnon de voyage en 2018 ... c'est la réponse que vous recherchiez. - russellpierce


Les noms d'hôte sont susceptibles de changer, lancez un whois contre votre IP publique:

if [[ ! -z $(whois $(curl -s shtuff.it/myip/short) | grep -i amazon) ]]; then 
  echo "I'm Amazon"
else 
  echo "I'm not Amazon"
fi

ou cliquez sur l'URL de méta-données AWS

if [[ ! -z $(curl -s http://169.254.169.254/1.0/) ]]; then 
  echo "I'm Amazon"
else 
  echo "I'm not Amazon"
fi

5
2017-07-02 14:09



Ajoutez un --connect-timeout 1 à la deuxième instruction curl pour un échec rapide si vous n’exécutez pas sur EC2. - Jonathan Oliver
FWIW, en utilisant l'URL de métadonnées pouvez indique qu'il est exécuté en tant qu'instance cloud, mais ne peut pas déterminer de manière concluante s'il s'agit spécifiquement d'EC2. OpenStack et Eucalyptus utilisent également le même URI de métadonnées. Je sais que cela ne va pas sans mal, mais pour mon travail, le fournisseur de cloud computing compte. - EmmEff


Cela fonctionne également bien pour les hôtes Linux dans ec2 et ne nécessite pas le réseau ni les délais d'attente associés:

grep -q amazon /sys/devices/virtual/dmi/id/bios_version

Cela fonctionne, car Amazon définit cette entrée comme suit:

$ cat /sys/devices/virtual/dmi/id/bios_version 4.2.amazon


5
2018-02-10 19:04



2018-05-01; semble invalide sur les instances M5 exécutant Ubuntu. - russellpierce


test -f /sys/hypervisor/uuid -a `head -c 3 /sys/hypervisor/uuid` == ec2 && echo yes

mais je ne sais pas à quel point c'est portable dans toutes les distributions.


3
2018-06-04 03:18



Eh bien, cela ne fonctionnera certainement pas sur les instances Windows EC2. - ceejayoz
Je préfère cette méthode car elle n'implique pas une interaction réseau pouvant se bloquer pour toutes sortes de raisons. L'utilisation des délais d'attente pour un échange HTTP n'est pas garantie pour empêcher les blocages. Je me fiche des instances de Windows. - Hannes
C'est exactement ce dont j'avais besoin! Bien mieux que de boucler quelque chose, merci! - qwertzguy
Pensez à utiliser l’UUID complet, au cas où un UUID d’hyperviseur d’un autre fournisseur commence également par «ec2». La probabilité que cela se produise est de 1 sur 4096, ce qui n’est pas négligeable. - Hannes
En fait, comparer l’UUID entier ne fonctionne pas car j’ai vu plusieurs UUID d’hyperviseurs différents dans la nature. Ils commencent tous par "ec2" cependant, donc cette réponse fonctionne telle quelle. - Hannes


Peut-être que vous pouvez utiliser "facter":

"Facter est une bibliothèque multiplate-forme permettant de récupérer des informations simples sur le système d’exploitation, telles que le système d’exploitation, la distribution Linux ou l’adresse MAC."

http://www.puppetlabs.com/puppet/related-projects/facter/

Par exemple, regardons le fait ec2 (facter-1.6.12 / lib / facter / ec2.rb):

require 'facter/util/ec2'
require 'open-uri'

def metadata(id = "")
  open("http://169.254.169.254/2008-02-01/meta-data/#{id||=''}").read.
    split("\n").each do |o|
    key = "#{id}#{o.gsub(/\=.*$/, '/')}"
    if key[-1..-1] != '/'
      value = open("http://169.254.169.254/2008-02-01/meta-data/#{key}").read.
        split("\n")
      symbol = "ec2_#{key.gsub(/\-|\//, '_')}".to_sym
      Facter.add(symbol) { setcode { value.join(',') } }
    else
      metadata(key)
    end
  end
end

def userdata()
  begin
    value = open("http://169.254.169.254/2008-02-01/user-data/").read.split
    Facter.add(:ec2_userdata) { setcode { value } }
  rescue OpenURI::HTTPError
  end
end

if (Facter::Util::EC2.has_euca_mac? || Facter::Util::EC2.has_openstack_mac? ||
    Facter::Util::EC2.has_ec2_arp?) && Facter::Util::EC2.can_connect?

  metadata
  userdata
else
  Facter.debug "Not an EC2 host"
end

2
2018-01-04 16:06