You can use, for example, Perl-compatible regular expressions. For instance:
alert tls any any -> any any (tls.sni; content: "suricata.io"; nocase; endswith; pcre:"/w.*\.suricata\.io$/"; msg:"Match on SNI wildcards"; sid:42; rev:1;)
would produce
{
"timestamp": "2023-07-22T16:39:55.905808+0200",
"flow_id": 1271632076972008,
"in_iface": "wlp61s0",
"event_type": "alert",
"src_ip": "192.168.178.25",
"src_port": 39434,
"dest_ip": "35.212.0.44",
"dest_port": 443,
"proto": "TCP",
"tx_id": 0,
"alert": {
"action": "allowed",
"gid": 1,
"signature_id": 42,
"rev": 1,
"signature": "Match on SNI wildcards",
"category": "",
"severity": 3
},
"tls": {
"sni": "www.suricata.io",
"version": "TLS 1.3",
"ja3": {},
"ja3s": {}
},
"app_proto": "tls",
"flow": {
"pkts_toserver": 4,
"pkts_toclient": 3,
"bytes_toserver": 789,
"bytes_toclient": 305,
"start": "2023-07-22T16:39:55.630760+0200"
}
}
{
"timestamp": "2023-07-22T16:39:56.111549+0200",
"flow_id": 1271632076972008,
"in_iface": "wlp61s0",
"event_type": "tls",
"src_ip": "192.168.178.25",
"src_port": 39434,
"dest_ip": "35.212.0.44",
"dest_port": 443,
"proto": "TCP",
"tls": {
"sni": "www.suricata.io",
"version": "TLS 1.3",
"ja3": {},
"ja3s": {}
}
}
You can easily adjust that to use your pass strategy and patterns.
What happens here is that you specify to match on the tls.sni sticky buffer. Then, you use the exact-matching content keyword to limit evaluation of further keywords to events in which the SNI already ends in suricata.io. Then, you can use the (more expensive) pcre keyword to specify a regular expression that can match more complex patterns. I think that approach generalizes well to your AWS domain structure.