1 of 43

Cloud Security

Best Practices

by Jonathan Marcil

February 2025

💧

☁️

🌨️

🌧️

2 of 43

  • Now and thenA bit of history, a bit of realization.
  • Security ImpactHow cloud providers are shaping security.
  • PatternsA security-related selection based on what is needed the most often in my experience.

Content overview

3 of 43

Boom! How it began.

Not so long ago, in the land of open source…

In an oversimplified fashion…

4 of 43

Install Linux

Install Platform App

Add your code

🗒️

5 of 43

Zoom! How it is now.

Evolution has come to this…

6 of 43

Select Cloud Provider

7 of 43

Select Cloud Provider

Select Cloud Service

420 services

(extracted from APIs)

8 of 43

9 of 43

10 of 43

Select Cloud Provider

Select Cloud Service

Add your code

🗒️

Setup Cloud Service

11 of 43

Meanwhile...

12 of 43

Cloud providers entered a race of repackaging apps that YOU have to select, configure and adapt your code to.

13 of 43

What does that do?

While concepts remains the same, you are vendor locked into a taxonomy and details…

You don’t have to think about OS level anymore…

You replace a lot of your code with services and their functionalities…

All of this isn’t inherently good or bad…

14 of 43

Impact on Security

You don’t have to think about OS level anymore…

Security at the OS level is rock solid, as experienced elite experts are doing the OS configuration, and even updating software for you.

Nothing can go wrong with that?

15 of 43

Until you need a particular update

What if you are using a software package and need it updated, and then the provider doesn’t update it quickly?

For you, it might a critical vulnerability, but for their total user base it’s not.

Sorry

This is not currently a priority on our roadmap.

16 of 43

Impact on Security

You replace a lot of your code with services and their functionalities…

Implementation of security protocols are secure and robust as tons of paid users share that “code base”, making it like a well maintained library

No cloud provider wants their service to be insecure…

17 of 43

Until you reconfigure for your need

It worked so easily out of the box, but what if you need a different setup than the default configuration.

What was easy and required little understanding of the system, now could rely on details to not be a misconfiguration that creates a breach.

Don’t forget that detail

It’s fast and easy to set up, but you need to remember some specific details.

18 of 43

What does that do?

While concepts remains the same, you are vendor locked into a taxonomy and details…

Secure integration is streamlined, services are (mostly) designed to fit together and security access controls works in an uniform fashion.

While nobody likes to see them self vendor locked, for security, uniformity makes it easier…

19 of 43

Until you need to integrate with another cloud or system

While the functionality is there, it’s sometimes gated by a higher tier paid price made for large scale enterprises.

The risk is when you are forced to stitch together a security solution for cross-cloud integration.

Integration supported but..

you need to understand the federation protocol and implementation details specific to all parties.

20 of 43

Don’t use email as primary key

In some clouds, email are mutable or unverified.

21 of 43

Microsoft Guidance

How do I know if my application is impacted?

Microsoft recommends reviewing application source code and determining whether the following patterns are present:

  • A mutable claim, such as email, is used for the purposes of uniquely identifying a user
  • A mutable claim, such as email is used for the purposes of authorizing a user's access to resources

These patterns are considered insecure, as users without a provisioned mailbox can have any email address set for their Mail (Primary SMTP) attribute. This attribute is not guaranteed to come from a verified email address. When an email claim with an unverified domain owner is used for authorization, any user without a provisioned mailbox has the potential to gain unauthorized access by changing their Mail attribute to impersonate another user.

An email is considered to be domain-owner verified if:

  • The domain belongs to the tenant where the user account resides, and the tenant admin has done verification of the domain
  • The email is from a Microsoft Account (MSA)
  • The email is from a Google account
  • The email was used for authentication using the one-time passcode (OTP) flow

It should also be noted that Facebook and SAML/WS-Fed accounts don't have verified domains.

This risk of unauthorized access has only been found in multi-tenant apps, as a user from one tenant could escalate their privileges to access resources from another tenant through modification of their Mail attribute.

22 of 43

Pause for dramatic effect

And maybe take a sip of water?

23 of 43

Security friendly cloud architecture patterns

These are a selection of some patterns I have concrete experience with.

24 of 43

HTTPS Load Balancer

25 of 43

For any HTTP URL you want to expose.

Plain text ports shouldn’t be associated with a public IP address.

TLS/SSL certificate management is handled by the cloud provider.

Variations exists for other protocols.

Hostname checking

SNI (multiple hosts on same IP) can serve the wrong hostname for your app, which can act unexpectedly.

crt.sh

When registering SSL certificate, transparency is a feature that expose all entries to the world.

$$$

In some cloud, choosing to manage your own SSL provider is easy, but might cost significant per month fees.

HTTPS Load Balancer

26 of 43

Good job Confoo!

Using wildcards to hide hosts

However, grouping of hosts should be used sparingly to segment security.

27 of 43

Authorization Proxy

28 of 43

Often done with the Load Balancer, “simple” to enable with defaults.

Adds a layer of authorization that can be connected to authentication managed by the cloud provider instead of your app.

Most likely will use something like OpenID Connect (OIDC) and OAuth2.

Authorization Proxy

29 of 43

Authorization Proxy: headers

Varies by cloud provider, and are added inline in every request by the proxy.

Your app receives them as request headers.

Headers Example (Azure)

{

'Disguised-Host': 'jonathan-test-headers.azurewebsites.net',

'Host': 'jonathan-test-headers.azurewebsites.net',

'X-Appservice-Proto': 'https',

'X-Client-Ip': '107.159.175.56',

'X-Client-Port': '56344',

'X-Forwarded-For': '107.159.175.56:56344',

'X-Forwarded-Proto': 'https',

'X-Forwarded-Tlsversion': '1.3',

'X-Ms-Client-Principal': 'eyJhdXR[...]xlIn0=',

'X-Ms-Client-Principal-Id': '9db[...]3',

'X-Ms-Client-Principal-Idp': 'aad',

'X-Ms-Client-Principal-Name': 'Jonathan Marcil',

'X-Ms-Token-Aad-Access-Token': 'eyJ0eXAi[...]L2QQ',

'X-Ms-Token-Aad-Expires-On': '2025-02-19T16:19:49.7332612Z',

'X-Ms-Token-Aad-Id-Token': 'eyJ0eX[...]X85TA',

'X-Ms-Token-Aad-Refresh-Token': '1.ASkA[...]0O-B',

'X-Original-Url': '/headers',

'X-Site-Deployment-Id': 'jonathan-test-headers'

}

30 of 43

Authorization Proxy: tokens

HTTP Headers sent to your app

Librairies exist to handle them in your application code, but under the hood it’s JWT tokens.

“Free” endpoints!

Some cloud proxies add endpoints over your app such as Azure’s /.auth/me to allow JavaScript to grab the tokens.

They also handle redirects URL for the OAuth2 flow.

31 of 43

Authorization Proxy: JWT

JSON Web Tokens contains claims that gives information about the logged in user

They are cryptographically signed to ensure authenticity

ID Token Example (Google)

{

"iss": "https://accounts.google.com",

"aud": "32555350559.apps.googleusercontent.com",

"sub": "111260650121185072906",

"hd": "google.com",

"email": "user@example.com",

"email_verified": "true",

"at_hash": "_LLKKivfvfme9eoQ3WcMIg",

"iat": "1650053185",

"exp": "1650056785",

"alg": "RS256",

"kid": "f1338ca26835863f671403941738a7b49e740fc0",

"typ": "JWT"

}

32 of 43

Understanding JWT, OAuth2 and OIDC can be counter-intuitive but rewarding when creating solutions

Scope creep!

This would require a serie of talks or even a training.

Okta made good documentation (google: “okta oauth2”) and each cloud provider have their own.

33 of 43

Essentially you can trust the cloud provider to handle protocol integration.

If your application require no authorization logic, you’re done.

However if you need to handle users, you have to be careful with your trust model.

Trusting headers

For high security needs, only trust signed headers.

If you trust other header, make sure they are safe (X-Client-IP and not X-Forwarded-For).

Trusting claims

Use unique cloud identifier to identify a user and not their email as they can be unverified or changed.

Trusting tokens

In your code, rely on libraries and make sure you are checking the signature of tokens using a hardcoded validation type.

Authorization Proxy

Zero trust

Your application shouldn’t do anything unless authorization goes thought.

34 of 43

Do it yourself

Envoy proxy is used in many big cloud providers to provide load balancing and handle the authorization layer.

Some providers will even admit that the solution is based on Envoy.

www.envoyproxy.io

35 of 43

Developer Access Tunnel

36 of 43

You have a service, could be a database or caching system that developers on their local machine need access to.

Some cloud providers might just offer to expose the service port with a public IP, and then it’s up to you to add restrictions.

A better alternative would be to provide a TLS-secured and authenticated path from their machine to the cloud.

Jumpbox

Create a SSH only instance in the same VPC network than the target service.

IP restrict this one!

Free logging

The tunnel gives you service access logs by having the SSH connection and/or IAM check loggable.

No-jumpbox

If you’re lucky your cloud will give you a facility to SSH and forward ports without the need to spin your own jumpbox.

Dev access tunnel

IAM

Major clouds will manage the access using their native IAM if you ssh using their command line tools.

37 of 43

Dev access tunnel: jumpbox

Plain old SSH port forwarding

ssh user@cloud-instance.provider.com -L 1234:10.1.1.4:5432

-L [local port]:[service ip]:[service port]

Inside the SSH instance

psql -h 10.1.1.4 -p 5432

On the local machine

psql -h localhost -p 1234

38 of 43

GitHub Deploys Without Keys

39 of 43

You want to deploy into your cloud using GitHub Actions.

Instead of using shared secrets, you can authorize GitHub repos to deploy.

Harder to configure, easier to handle security as you rely on GitHub claims.

Validate org by org id

When you configure your cloud, make sure you validate the repository_owner_id and not just the repo name (not unique) or org name (can change over time).

GitHub Actions OIDC

Official GitHub Documentation

40 of 43

Cloud Logging

Encryption at REST

41 of 43

Some small patterns for quick wins

  • Use Cloud Logging �You might need to enable and configure it, but you can get write-only logs that are useful for high security level requirements.
  • Encryption at restThis is basically free with cloud storage; no need to worry about someone stealing your hard-drive.

Flash round

At rest limits

Doesn’t protect access to your data from any of the applications that has access to storage.��Use IAM with the level you need.

42 of 43

Maps the patterns into AWS, Azure, GCP

jonathanmarcil.ca/cloud-security

Cloud Security Cheat Sheet

43 of 43

Slides and links on:

about.jonathanmarcil.ca 👉

Special thanks to:

IVADO Labs

Confoo 2025

Camile

THANKS!