Aller au contenu

ACM

Nos services sont maintenant résilients/HA et redondés.

Par contre, on est toujours en HTTP, il serait temps de passer en HTTPS.

Aussi, imaginons que nous voulons étendre un peu notre service à l'international et commencer à optimiser l'expérience utilisateur. Pour cela, on va commencer par utiliser le CDN (Content delivery network) d'AWS qui s'appelle CloudFront.

Et en bonus, on va se servir de la capacité S3 pour servir un site web statique dans une approche serverless, ce qui nous permettra de ne plus avoir à provisionner des serveurs pour le front.

Concepts

ACM

AWS Certificate Manager (ACM) est le service permettant de générer, stocker et renouveler nos certificats SSL/TLS.

Le service est gratuit, mais les clés y sont protégées et l'on ne peut pas les récupérer. En effet, le service est intégré avec beaucoup services AWS utilisant les certificats (Liste ici). Cela permet d'éviter de potentielles fuites de secrets.

Note

Par contre on ne peut donc pas s'en servir directement depuis un EC2. On est en effet obligé de passer par un autre service comme ELB ou CloudFront

On peut également importer des certificats que l'on aurait générés ailleurs.

Les certificats générés par ACM sont DV, Domain Validated. C'est-à-dire que ACM vérifie uniquement que l'on maitrise bien le domaine (ou zone DNS) pour lequel on génère un certificat. D'autres fournisseurs de certificats pourront proposer ces certificats OV ou EV payants pour lesquels il y aura des vérifications faites sur la légitimité/authenticité de l'entreprise, comme GlobalSign, DigiCert, GeoTrust...

Pour faire cette validation de domaine, ACM propose 2 solutions :

  • Validation DNS : ACM fourni des entrées DNS à créer dans notre zone.
  • Validation Email : un email est envoyé aux administrateurs du domaine contenant les liens à cliquer.

On préfère l'usage de la validation DNS car elle est plus automatisable. De plus ACM est intégré avec Route53 et sur mise à jour de certificats le renouvellement est automatique si l'entrée est toujours présente.

Note

Quand on parle de certificat public. On parle bien de certificat signée par une autorité trustée par tous les navigateurs/clients et pas signée par une autorité privée. Chose que AWS supporte, c'est-à-dire que l'on peut déléguer la gestion d'une private CA/PKI à AWS grace à AWS Private CA.

Ne donc pas confondre avec les clés privées et publiques.

Note

Cloudfront est un service global mais pour qu'il puisse se servir des certificats ACM, service lui régional, il faut les placer dans la region us-east-1.

TP

À vous de jouer

Le but de cette étape est de passer votre site web et API en HTTPS.

Pour cela, nous allons générer nos 2 certificats via ACM et s'en servir avec les intégrations du service avec CloudFront et notre ALB. Nous allons pouvoir réutiliser notre domaine en www.

Nous allons nous servir du module terraform ACM. Celui-ci génère pour nous notre certificat et la création des records Route53 pour la validation DNS.

  • Vous pouvez continuer dans le même dossier Step5
  • Vous pouvez commencer par votre api :
    • Déclarez un module acm_certificate dans votre module compute, vous pourrez passer le domain_name et la zone_id en input
    • Éditez le listener de votre ALB pour changer son protocol en HTTPS, son port en 443, et ajoutez ssl_policy = "ELBSecurityPolicy-2016-08"
    • Pensez au port du security group de l'ALB de l'API qui doit aussi changer.
  • Vous pourrez ensuite passer au site web
    • Utilisez le module ACM pour générer le certificat
    • Changer les viewer_protocol_policy de votre distribution pour forcer le https via redirect-to-https
    • Éditez le block viewer_certificate avec
      • l'ARN de votre certificat généré
      • ssl_support_method = "sni-only"
      • minimum_protocol_version = "TLSv1.2_2021"
    • Ajouter un aliases à la distribution avec votre FQDN

Note

Attention pour rappel CloudFront nécessite un certificat dans la région us-east-1.

Vous devez donc déclarer un nouveau provider AWS. Vous dever lui donner un alias que vous pouvez nommer us-east-1

Note

Votre API_URL ayant changée dans le main.xxx.js vous devez invalider le cache !

Success

Vous avez désormais passé votre API et votre site web en HTTPS !

Bonus

CloudFront function

L'idée de ce bonus est de mettre en place une CloudFront function viewer-request permettant de faire une authentification Basic.

Code

Voici le code de la fonction.

scripts/frontend_auth.js
'use strict';
function handler(event) {
    // Get request and request headers
    const headers = event.request.headers;

    // Configure authentication
    const authUser = 'admin';
    const authPass = 'toto';

    // Construct the Basic Auth string
    const authString = 'Basic ' + Buffer.from(authUser + ':' + authPass).toString('base64');

    // If the authentication header is matching the preferred authentication
    // then return the request to the origin
    if (headers.authorization !== undefined && headers.authorization.value !== undefined && headers.authorization.value === authString) {
        return event.request;
    }
    // If the authentication header is not matching the preferred authentication
    // then return a 401 response to the client
    // this will trigger the browser to show the authentication dialog
    return {
        statusCode: 401,
        statusDescription: 'Unauthorized',
        headers: {
            'www-authenticate': {value:'Basic realm="Enter your credentials"'}
        },
    };
}

Warning

Avoir fait cette étape avant aurait impliqué de faire passer l'authentification en clair sans TLS ce qui est vraiment une mauvaise idée.

Ici seul le site web est "protégé" par une authentification et pas l'API.

L'authentification basic n'est pas vraiment le meilleur moyen aujourd'hui pour gérer une authentification. L'OIDC ou SAML 2.0 sont aujourd'hui les protocols les plus courants permettant de faire de SSO. AWS Cognito est le service managé permettant notemment de gérer ses utilisateurs et leur authentification via ces protocols.