Corexpert & TeamWork Blog

Planifiez vos tâches CRON avec AWS

Utilisé en conjonction avec Amazon CloudWatch Events, Amazon SNS permet le déclenchement de tâches CRON appelant des web services. Nous allons voir dans ce post comment mettre cela en place facilement.

Dans un premier temps, il nous faut créer un topic SNS.

Puis, créer une subscription vers la route du web service. Ainsi, à chaque publication dans le topic SNS par l’event Cloud Watch, une notification sera envoyée à la route HTTP définie.

Avant de créer cette subscription, il faut savoir que toute subscription nécessite une confirmation dont la demande est envoyée à la cible. La demande de confirmation est envoyée lors de la création de la subscription mais celle-ci peut être faite manuellement via la console AWS.

Voici un exemple de code PHP qui vérifie la signature des messages envoyés par Amazon SNS et confirme automatiquement la subscription au topic :

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $postContent = file_get_contents('php://input');
  $message = json_decode($postContent);
  if( !empty($message->Type) ) {
    /** Vérification de la signature de la notification SNS pour la version 1 **/ 
    if( $message->SignatureVersion == '1' ){
        /** Vérification de l'URL de signature */
      $parsedURL = parse_url($message->SigningCertURL);
      if (empty($parsedURL['scheme'])
          || empty($parsedURL['host'])
          || $parsedURL['scheme'] !== 'https'
          || substr($message->SigningCertURL, -4) !== '.pem'
          || !preg_match('/^sns\.[a-zA-Z0-9\-]{3,}\.amazonaws\.com(\.cn)?$/', $parsedURL['host'])
      ) {
           throw new Exception('The certificate is located on an invalid domain.');
      }
      $certificate = file_get_contents($message->SigningCertURL);
      /** Récupération de la clé publique et de la signature du message**/
      $publicKey = openssl_get_publickey($certificate);
      if (!$publicKey) {
          throw new Exception('Cannot get the public key from the certificate.');
      }
      $signature = base64_decode($message->Signature);
      
      /** Création du string à signer **/
      $signableKeys = ['Message','MessageId','Subject','SubscribeURL','Timestamp','Token','TopicArn','Type'];
      $stringToSign = "";
      foreach($signableKeys as $key){
          if (isset($message->$key)) {
              $stringToSign .= "{$key}\n{$message->$key}\n";
          }
      }
      /** vérification de la signature du message **/
      if (!openssl_verify($stringToSign, $signature, $publicKey, OPENSSL_ALGO_SHA1)) {
          throw new Exception('The message signature is invalid.');
      }
    }
    else{
        throw new Exception('Signature Version not supported');
    }

    /** Confirmation de l'insciption au topic SNS */
    if($message->Type === "SubscriptionConfirmation"){
        file_get_contents($message->SubscribeURL);
    }

    /** CODE A EXECUTER DANS LA TACHE */
  }
}

Enfin, il ne nous reste plus qu’a créer une rule pour déclencher un Event Amazon CloudWatch selon un Schedule qui publiera dans ce topic tous les x minutes/heures/jours . 

Et voilà ! notre web service est maintenant appelé toutes les 5 minutes.

Comments

comments