Skip to content

Commit

Permalink
add mtls support
Browse files Browse the repository at this point in the history
Signed-off-by: sal rashid <[email protected]>
  • Loading branch information
salrashid123 committed Aug 14, 2024
1 parent 0d0c12d commit 5dfe8e1
Show file tree
Hide file tree
Showing 10 changed files with 334 additions and 7 deletions.
72 changes: 69 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,30 @@ and run any application using ADC:

from google.cloud import storage
import google.auth

import google.auth.compute_engine
import google.auth.transport.requests

from google.auth.compute_engine import _metadata


## with ADC metadata server

credentials, project = google.auth.default()
client = storage.Client(credentials=credentials)
buckets = client.list_buckets()
for bkt in buckets:
print(bkt)


## as compute credential

creds = google.auth.compute_engine.Credentials()
session = google.auth.transport.requests.AuthorizedSession(creds)
r = session.get('https://www.googleapis.com/userinfo/v2/me').json()
print(str(r))


## get arbitrary metadata values directly

request = google.auth.transport.requests.Request()
print(_metadata.get_project_id(request))
print(_metadata.get(request,"instance/id"))
Expand Down Expand Up @@ -280,6 +284,10 @@ You can set the following options on usage:
| **`-metricsInterface`** | Prometheus metrics interface (default: 127.0.0.1) |
| **`-metricsPort`** | Prometheus metrics port (default: 9000) |
| **`-metricsPath`** | Prometheus metrics path (default: /metrics) |
| **`-usemTLS`** | Start server with mtls (default: false) |
| **`-rootCAmTLS`** | Root CA for mtls client validation (default: `certs/root.crt`) |
| **`-serverCert`** | Server certificate for mtls (default: `certs/server.crt`) |
| **`-serverKey`** | Server key for mtls (default: `certs/server.key`) |

### With JSON ServiceAccount file

Expand Down Expand Up @@ -425,7 +433,7 @@ openssl rsa -in /tmp/f.json -out /tmp/key_rsa.pem

printf '\x00\x00' > unique.dat
tpm2_createprimary -C o -G ecc -g sha256 -c primary.ctx -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt" -u unique.dat
# tpm2_createprimary -C o -G ecc -g sha256 -c primary.ctx -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt"

tpm2_import -C primary.ctx -G rsa2048:rsassa:null -g sha256 -i /tmp/key_rsa.pem -u key.pub -r key.prv
tpm2_flushcontext -t
tpm2_load -C primary.ctx -u key.pub -r key.prv -c key.ctx
Expand All @@ -434,6 +442,7 @@ tpm2_flushcontext -t
tpm2_evictcontrol -C o -c key.ctx 0x81010002

# if you have tpm2-tss-engine installed, you can save as encrypted PEM
## or use https://github.com/salrashid123/tpm2genkey
# tpm2tss-genkey -u key.pub -r key.prv private.pem

## which formats it as TPM-encrypted PEM:
Expand Down Expand Up @@ -933,6 +942,9 @@ socat TCP-LISTEN:8080,fork,reuseaddr UNIX-CONNECT:/tmp/metadata.sock
If you want to build the server using bazel (eg, [deterministic](https://github.com/salrashid123/go-grpc-bazel-docker)),

```bash
# $ bazel version
# Build label: 6.2.1

## generate dependencies
# bazel run :gazelle -- update-repos -from_file=go.mod -prune=true -to_macro=repositories.bzl%go_repositories

Expand Down Expand Up @@ -1023,6 +1035,60 @@ $ cosign verify [email protected] --certificate-oid
# $ rekor-cli get --rekor_server https://rekor.sigstore.dev --log-index $LogIndex --format=json | jq '.'
```

## GCE mTLS

GCE metadata server also supports a mode where [mTLS is used](https://cloud.google.com/compute/docs/metadata/overview#https-mds)

You can enable this mode with the following flags but be aware, no client library supports it afaik.

```bash
./gce_metadata_server -logtostderr --configFile=config.json \
-alsologtostderr -v 5 \
-port :8080 --usemTLS \
--serverCert certs/server.crt \
--serverKey certs/server.key --rootCAmTLS certs/root.crt \
--serviceAccountFile certs/metadata-sa.json

curl -s -H 'Metadata-Flavor: Google' --connect-to metadata.google.internal:443:127.0.0.1:8080 \
--cert certs/client.crt --key certs/client.key --cacert certs/root.crt \
https://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
```

For an example on how the [GCE guest agent](https://github.com/GoogleCloudPlatform/guest-agent/blob/main/google_guest_agent/agentcrypto/mtls_mds.go#L136) extracts the root ca from UEFI and decrypts the client cert/key from metadata server, see [certextract.go](https://gist.github.com/salrashid123/c1de41bf380c1f9a3602675276977e48)

Note that GCE issues client certificates that are rotated periodically. Infact, the client certificate is set to expire in a week:

For example, the client certificate from a real GCE instance with metadata TLS shows a validity for about a week.

```bash
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
82:f6:44:68:9e:b5:b2:cc:81:35:ff:29:61:1d:bf:9e
Signature Algorithm: ecdsa-with-SHA256
Issuer: C=US, O=Google Compute Internal, CN=google.internal
Validity
Not Before: Aug 13 23:05:26 2024 GMT
Not After : Aug 20 23:10:26 2024 GMT
Subject: C=US, O=Google Compute Engine, CN=instance-1
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Key Usage: critical
Digital Signature
X509v3 Subject Alternative Name:
DNS:instance-1.c.srashid-test2.internal
X509v3 Extended Key Usage: critical
TLS Web Client Authentication
Signature Algorithm: ecdsa-with-SHA256
```

## Metrics

Basic latency and counter Prometheus metrics are enabled using the `--metrisEnabled` flag.
Expand Down
5 changes: 5 additions & 0 deletions certs/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
exports_files([
"root.crt",
"server.crt",
"server.key",
])
54 changes: 54 additions & 0 deletions certs/client.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 3 (0x3)
Signature Algorithm: ecdsa-with-SHA256
Issuer: C=US, O=Google Compute Internal, CN=google.internal
Validity
Not Before: Aug 14 00:45:56 2024 GMT
Not After : Aug 14 00:45:56 2034 GMT
Subject: C=US, O=Google Compute Internal, CN=instance-1
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:3b:62:92:bf:77:9e:a1:23:97:1e:7c:cd:44:9d:
54:6d:52:76:2e:58:1a:86:aa:c2:5f:93:77:c1:02:
13:84:1c:ec:0b:c5:b1:7e:24:4e:47:a6:1c:6d:e1:
ac:6d:6c:72:d2:86:12:aa:81:de:00:5b:f0:68:7a:
3d:cf:ea:e9:62
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Basic Constraints:
CA:FALSE
X509v3 Extended Key Usage:
TLS Web Client Authentication
X509v3 Subject Key Identifier:
DE:F7:60:35:49:71:E7:DE:BE:D3:CE:7A:13:34:5F:02:1E:02:19:EB
X509v3 Subject Alternative Name:
DNS:instance-1.c.srashid-test2.internal
X509v3 Authority Key Identifier:
45:C6:27:32:EA:35:73:21:78:23:25:99:49:5E:6A:68:1F:0B:2F:ED
Signature Algorithm: ecdsa-with-SHA256
Signature Value:
30:45:02:21:00:cc:8f:73:8e:47:5f:c8:f3:8e:c1:c0:21:c2:
1c:dc:ac:df:54:a2:03:3a:66:d5:cd:3e:db:d4:80:d3:1a:fb:
2d:02:20:02:61:d3:8e:d8:8e:74:3b:1e:d1:6c:1f:16:2e:f2:
73:12:2c:57:a1:d1:bd:6a:94:e9:e7:12:55:df:74:7a:2f
-----BEGIN CERTIFICATE-----
MIICIDCCAcagAwIBAgIBAzAKBggqhkjOPQQDAjBJMQswCQYDVQQGEwJVUzEgMB4G
A1UECgwXR29vZ2xlIENvbXB1dGUgSW50ZXJuYWwxGDAWBgNVBAMMD2dvb2dsZS5p
bnRlcm5hbDAeFw0yNDA4MTQwMDQ1NTZaFw0zNDA4MTQwMDQ1NTZaMEQxCzAJBgNV
BAYTAlVTMSAwHgYDVQQKDBdHb29nbGUgQ29tcHV0ZSBJbnRlcm5hbDETMBEGA1UE
AwwKaW5zdGFuY2UtMTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDtikr93nqEj
lx58zUSdVG1Sdi5YGoaqwl+Td8ECE4Qc7AvFsX4kTkemHG3hrG1sctKGEqqB3gBb
8Gh6Pc/q6WKjgaMwgaAwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQCMAAwEwYDVR0l
BAwwCgYIKwYBBQUHAwIwHQYDVR0OBBYEFN73YDVJcefevtPOehM0XwIeAhnrMC4G
A1UdEQQnMCWCI2luc3RhbmNlLTEuYy5zcmFzaGlkLXRlc3QyLmludGVybmFsMB8G
A1UdIwQYMBaAFEXGJzLqNXMheCMlmUleamgfCy/tMAoGCCqGSM49BAMCA0gAMEUC
IQDMj3OOR1/I847BwCHCHNys31SiAzpm1c0+29SA0xr7LQIgAmHTjtiOdDse0Wwf
Fi7ycxIsV6HRvWqU6ecSVd90ei8=
-----END CERTIFICATE-----
5 changes: 5 additions & 0 deletions certs/client.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/sVz1HH1Xa1T9ccT
IUfymQGkh9RLHskD0RYCBYJBCIShRANCAAQ7YpK/d56hI5cefM1EnVRtUnYuWBqG
qsJfk3fBAhOEHOwLxbF+JE5Hphxt4axtbHLShhKqgd4AW/Boej3P6uli
-----END PRIVATE KEY-----
49 changes: 49 additions & 0 deletions certs/root.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: ecdsa-with-SHA256
Issuer: C=US, O=Google Compute Internal, CN=google.internal
Validity
Not Before: Aug 14 00:38:35 2024 GMT
Not After : Aug 14 00:38:35 2034 GMT
Subject: C=US, O=Google Compute Internal, CN=google.internal
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:61:27:e7:d9:8d:e5:b1:a4:a9:0d:94:54:67:ce:
d2:08:8a:42:fc:7b:14:bd:5e:de:33:f0:42:0f:10:
4d:f7:58:8f:95:32:5e:d9:71:61:0a:47:b9:84:0f:
24:b8:28:d9:c0:03:dc:f0:0b:ed:37:16:d7:87:69:
40:77:f3:41:e6
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
X509v3 Subject Key Identifier:
45:C6:27:32:EA:35:73:21:78:23:25:99:49:5E:6A:68:1F:0B:2F:ED
X509v3 Subject Alternative Name:
DNS:google.internal
Signature Algorithm: ecdsa-with-SHA256
Signature Value:
30:45:02:21:00:c3:71:43:51:27:3a:71:82:1d:85:76:91:10:
55:9f:e2:80:2d:12:16:2b:01:ea:d9:33:dd:68:28:f4:8f:5e:
fd:02:20:0b:96:d8:8d:6b:0a:cf:a9:35:48:aa:0f:7f:17:4d:
d5:b4:6e:f8:a3:32:cb:da:cc:76:85:91:e0:cd:52:6a:b1
-----BEGIN CERTIFICATE-----
MIIB4jCCAYigAwIBAgIBATAKBggqhkjOPQQDAjBJMQswCQYDVQQGEwJVUzEgMB4G
A1UECgwXR29vZ2xlIENvbXB1dGUgSW50ZXJuYWwxGDAWBgNVBAMMD2dvb2dsZS5p
bnRlcm5hbDAeFw0yNDA4MTQwMDM4MzVaFw0zNDA4MTQwMDM4MzVaMEkxCzAJBgNV
BAYTAlVTMSAwHgYDVQQKDBdHb29nbGUgQ29tcHV0ZSBJbnRlcm5hbDEYMBYGA1UE
AwwPZ29vZ2xlLmludGVybmFsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYSfn
2Y3lsaSpDZRUZ87SCIpC/HsUvV7eM/BCDxBN91iPlTJe2XFhCke5hA8kuCjZwAPc
8AvtNxbXh2lAd/NB5qNhMF8wDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB
Af8CAQAwHQYDVR0OBBYEFEXGJzLqNXMheCMlmUleamgfCy/tMBoGA1UdEQQTMBGC
D2dvb2dsZS5pbnRlcm5hbDAKBggqhkjOPQQDAgNIADBFAiEAw3FDUSc6cYIdhXaR
EFWf4oAtEhYrAerZM91oKPSPXv0CIAuW2I1rCs+pNUiqD38XTdW0bvijMsvazHaF
keDNUmqx
-----END CERTIFICATE-----
54 changes: 54 additions & 0 deletions certs/server.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 2 (0x2)
Signature Algorithm: ecdsa-with-SHA256
Issuer: C=US, O=Google Compute Internal, CN=google.internal
Validity
Not Before: Aug 14 00:43:09 2024 GMT
Not After : Aug 14 00:43:09 2034 GMT
Subject: C=US, O=Google Compute Internal, CN=localhost
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:35:3e:3a:36:07:a1:af:20:3c:0a:63:a3:e7:a8:
46:d8:ea:a5:43:59:77:95:99:5f:a8:46:13:dc:35:
a0:ea:07:fc:03:00:8e:48:b9:58:35:b7:74:97:56:
bc:66:bb:10:32:53:8c:ed:f0:31:89:90:88:04:cf:
3a:f5:b0:35:fc
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Basic Constraints:
CA:FALSE
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Key Identifier:
24:39:51:99:2E:66:31:BA:0E:28:11:8B:5D:0B:BD:C6:62:80:8E:4F
X509v3 Subject Alternative Name:
DNS:metadata.google.internal, IP Address:169.254.169.254
X509v3 Authority Key Identifier:
45:C6:27:32:EA:35:73:21:78:23:25:99:49:5E:6A:68:1F:0B:2F:ED
Signature Algorithm: ecdsa-with-SHA256
Signature Value:
30:45:02:21:00:a8:32:81:90:4a:fe:92:51:b8:5d:0a:77:4c:
2d:39:3c:4e:91:ec:1a:d2:81:6c:aa:3a:75:a1:ec:06:84:89:
b8:02:20:46:c0:15:f5:12:0c:d0:d5:fe:45:e5:b0:e2:f0:93:
a8:c0:71:03:ce:48:52:5a:46:58:b4:9f:a3:cc:1d:d8:51
-----BEGIN CERTIFICATE-----
MIICGjCCAcCgAwIBAgIBAjAKBggqhkjOPQQDAjBJMQswCQYDVQQGEwJVUzEgMB4G
A1UECgwXR29vZ2xlIENvbXB1dGUgSW50ZXJuYWwxGDAWBgNVBAMMD2dvb2dsZS5p
bnRlcm5hbDAeFw0yNDA4MTQwMDQzMDlaFw0zNDA4MTQwMDQzMDlaMEMxCzAJBgNV
BAYTAlVTMSAwHgYDVQQKDBdHb29nbGUgQ29tcHV0ZSBJbnRlcm5hbDESMBAGA1UE
AwwJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENT46NgehryA8
CmOj56hG2OqlQ1l3lZlfqEYT3DWg6gf8AwCOSLlYNbd0l1a8ZrsQMlOM7fAxiZCI
BM869bA1/KOBnjCBmzAOBgNVHQ8BAf8EBAMCB4AwCQYDVR0TBAIwADATBgNVHSUE
DDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUJDlRmS5mMboOKBGLXQu9xmKAjk8wKQYD
VR0RBCIwIIIYbWV0YWRhdGEuZ29vZ2xlLmludGVybmFshwSp/qn+MB8GA1UdIwQY
MBaAFEXGJzLqNXMheCMlmUleamgfCy/tMAoGCCqGSM49BAMCA0gAMEUCIQCoMoGQ
Sv6SUbhdCndMLTk8TpHsGtKBbKo6daHsBoSJuAIgRsAV9RIM0NX+ReWw4vCTqMBx
A85IUlpGWLSfo8wd2FE=
-----END CERTIFICATE-----
5 changes: 5 additions & 0 deletions certs/server.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgMjkAbQkHg5B//QQL
FS1vVM34kajQa1dQhMDkp8NR8H2hRANCAAQ1Pjo2B6GvIDwKY6PnqEbY6qVDWXeV
mV+oRhPcNaDqB/wDAI5IuVg1t3SXVrxmuxAyU4zt8DGJkIgEzzr1sDX8
-----END PRIVATE KEY-----
12 changes: 11 additions & 1 deletion cmd/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ go_library(
],
)

pkg_tar(
name = "certs_bundle",
srcs = [
"//certs:root.crt",
"//certs:server.crt",
"//certs:server.key",
],
package_dir = "/certs",
)

pkg_tar(
name = "config_bundle",
srcs = [
Expand All @@ -55,7 +65,7 @@ pkg_tar(
oci_image(
name = "server-image",
base = "@distroless_base",
tars = [":config_bundle", ":app-tar"],
tars = [":config_bundle", ":certs_bundle", ":app-tar"],
entrypoint = ["/gce_metadata_server"],
cmd = [],
env = {},
Expand Down
16 changes: 16 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ var (
keyPass = flag.String("keyPass", "", "TPM Key password")
pcrs = flag.String("pcrs", "", "PCR Bound value (increasing order, comma separated)")
sessionEncryptionName = flag.String("tpm-session-encrypt-with-name", "", "hex encoded TPM object 'name' to use with an encrypted session")

usemTLS = flag.Bool("usemTLS", false, "Use mTLS")
rootCAmTLS = flag.String("rootCAmTLS", "certs/root.crt", "rootCA to validate client certs ")
serverCert = flag.String("serverCert", "certs/server.crt", "Server mtls certificate")
serverKey = flag.String("serverKey", "certs/server.key", "Server mtls key")
)

var TPMDEVICES = []string{"/dev/tpm0", "/dev/tpmrm0"}
Expand Down Expand Up @@ -372,6 +377,13 @@ func main() {

}

if *usemTLS && (*rootCAmTLS == "" || *serverCert == "" || *serverKey == "") {
if err != nil {
glog.Errorf("Must specify rootCAmTLS, serverCert and serverKey if useMTLS is set")
os.Exit(1)
}
}

serverConfig := &mds.ServerConfig{
BindInterface: *bindInterface,
Port: *port,
Expand All @@ -386,6 +398,10 @@ func main() {
MetricsInterface: *metricsInterface,
MetricsPort: *metricsPort,
MetricsPath: *metricsPath,
UsemTLS: *usemTLS,
RootCAmTLS: *rootCAmTLS,
ServerCert: *serverCert,
ServerKey: *serverKey,
}

f, err := mds.NewMetadataServer(ctx, serverConfig, creds, claims)
Expand Down
Loading

0 comments on commit 5dfe8e1

Please sign in to comment.