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.
- Déclarez un module
- 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 viaredirect-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.
'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.