From 5dfe8e1dc5d62995426ea20cd520738b0f951486 Mon Sep 17 00:00:00 2001 From: sal rashid Date: Wed, 14 Aug 2024 11:11:33 -0400 Subject: [PATCH] add mtls support Signed-off-by: sal rashid --- README.md | 72 +++++++++++++++++++++++++++++++++++++++++++++-- certs/BUILD.bazel | 5 ++++ certs/client.crt | 54 +++++++++++++++++++++++++++++++++++ certs/client.key | 5 ++++ certs/root.crt | 49 ++++++++++++++++++++++++++++++++ certs/server.crt | 54 +++++++++++++++++++++++++++++++++++ certs/server.key | 5 ++++ cmd/BUILD.bazel | 12 +++++++- cmd/main.go | 16 +++++++++++ server.go | 69 +++++++++++++++++++++++++++++++++++++++++++-- 10 files changed, 334 insertions(+), 7 deletions(-) create mode 100644 certs/BUILD.bazel create mode 100644 certs/client.crt create mode 100644 certs/client.key create mode 100644 certs/root.crt create mode 100644 certs/server.crt create mode 100644 certs/server.key diff --git a/README.md b/README.md index b669bd2..e77dc9c 100644 --- a/README.md +++ b/README.md @@ -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")) @@ -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 @@ -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 @@ -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: @@ -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 @@ -1023,6 +1035,60 @@ $ cosign verify --certificate-identity=salrashid123@gmail.com --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. diff --git a/certs/BUILD.bazel b/certs/BUILD.bazel new file mode 100644 index 0000000..2d37585 --- /dev/null +++ b/certs/BUILD.bazel @@ -0,0 +1,5 @@ +exports_files([ + "root.crt", + "server.crt", + "server.key", + ]) \ No newline at end of file diff --git a/certs/client.crt b/certs/client.crt new file mode 100644 index 0000000..1df2178 --- /dev/null +++ b/certs/client.crt @@ -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----- diff --git a/certs/client.key b/certs/client.key new file mode 100644 index 0000000..a35259a --- /dev/null +++ b/certs/client.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/sVz1HH1Xa1T9ccT +IUfymQGkh9RLHskD0RYCBYJBCIShRANCAAQ7YpK/d56hI5cefM1EnVRtUnYuWBqG +qsJfk3fBAhOEHOwLxbF+JE5Hphxt4axtbHLShhKqgd4AW/Boej3P6uli +-----END PRIVATE KEY----- diff --git a/certs/root.crt b/certs/root.crt new file mode 100644 index 0000000..b481d4a --- /dev/null +++ b/certs/root.crt @@ -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----- diff --git a/certs/server.crt b/certs/server.crt new file mode 100644 index 0000000..ad6c486 --- /dev/null +++ b/certs/server.crt @@ -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----- diff --git a/certs/server.key b/certs/server.key new file mode 100644 index 0000000..59c2dff --- /dev/null +++ b/certs/server.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgMjkAbQkHg5B//QQL +FS1vVM34kajQa1dQhMDkp8NR8H2hRANCAAQ1Pjo2B6GvIDwKY6PnqEbY6qVDWXeV +mV+oRhPcNaDqB/wDAI5IuVg1t3SXVrxmuxAyU4zt8DGJkIgEzzr1sDX8 +-----END PRIVATE KEY----- diff --git a/cmd/BUILD.bazel b/cmd/BUILD.bazel index 4e2c81b..01011cd 100644 --- a/cmd/BUILD.bazel +++ b/cmd/BUILD.bazel @@ -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 = [ @@ -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 = {}, diff --git a/cmd/main.go b/cmd/main.go index aa2d455..5081247 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -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"} @@ -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, @@ -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) diff --git a/server.go b/server.go index a762ff6..6209f8a 100644 --- a/server.go +++ b/server.go @@ -24,7 +24,10 @@ package mds import ( "bytes" "crypto/md5" + "crypto/tls" + "crypto/x509" "encoding/json" + "encoding/pem" "errors" "io" "net" @@ -44,7 +47,6 @@ import ( jwt "github.com/golang-jwt/jwt/v5" "github.com/golang/glog" tpmjwt "github.com/salrashid123/golang-jwt-tpm" - "golang.org/x/net/http2" "golang.org/x/oauth2" "google.golang.org/api/idtoken" @@ -194,6 +196,11 @@ type ServerConfig struct { AuthSession tpmjwt.Session // auth session to use EncryptionHandle tpm2.TPMHandle // (optional) handle to use for transit encryption EncryptionPub *tpm2.TPMTPublic // (optional) public key to use for transit encryption + + UsemTLS bool // toggle if mtls is used (default: false) + RootCAmTLS string // ca to validate client certs (default "") + ServerCert string // server certificate for mtls (default: "") + ServerKey string // server key for mtls (default: "") } func prometheusMiddleware(next http.Handler) http.Handler { @@ -1134,7 +1141,6 @@ func (h *MetadataServer) Start() error { var err error h.srv = &http.Server{Handler: m} - http2.ConfigureServer(h.srv, &http2.Server{}) if h.ServerConfig.DomainSocket != "" { glog.Infof("domain socket specified, ignoring TCP listers, %s", h.ServerConfig.DomainSocket) @@ -1143,6 +1149,61 @@ func (h *MetadataServer) Start() error { glog.Errorf("Error listening to domain socket: %v\n", err) return err } + } else if h.ServerConfig.UsemTLS { + clientCaCert, err := os.ReadFile(h.ServerConfig.RootCAmTLS) + if err != nil { + glog.Errorf("Error reading mtls ca: %v\n", err) + return err + } + clientCaCertPool := x509.NewCertPool() + clientCaCertPool.AppendCertsFromPEM(clientCaCert) + + serverCertBytes, err := os.ReadFile(h.ServerConfig.ServerCert) + if err != nil { + glog.Errorf("ERROR: Failed to parse server certificate: %s", err) + return err + } + + blockpulic, _ := pem.Decode(serverCertBytes) + + clientCertificate, err := x509.ParseCertificate(blockpulic.Bytes) + if err != nil { + glog.Errorf("ERROR: Failed to parse certificate: %s", err) + return err + } + + serverKeyBytes, err := os.ReadFile(h.ServerConfig.ServerKey) + if err != nil { + glog.Errorf("ERROR: Failed to parse server key: %s", err) + return err + } + + blockKey, _ := pem.Decode(serverKeyBytes) + + clientKey, err := x509.ParsePKCS8PrivateKey(blockKey.Bytes) + if err != nil { + glog.Errorf("ERROR: Failed to parse ec key: %s", err) + return err + } + + tlsCrt := tls.Certificate{ + Certificate: [][]byte{clientCertificate.Raw}, + Leaf: clientCertificate, + PrivateKey: clientKey, + } + + tc := &tls.Config{ + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: clientCaCertPool, + Certificates: []tls.Certificate{tlsCrt}, + } + + glog.Infof("tcp TLS socket specified %s", fmt.Sprintf("%s%s", h.ServerConfig.BindInterface, h.ServerConfig.Port)) + l, err = tls.Listen("tcp", fmt.Sprintf("%s%s", h.ServerConfig.BindInterface, h.ServerConfig.Port), tc) + if err != nil { + glog.Errorf("Error listening to tcp socket: %v\n", err) + return err + } } else { glog.Infof("tcp socket specified %s", fmt.Sprintf("%s%s", h.ServerConfig.BindInterface, h.ServerConfig.Port)) l, err = net.Listen("tcp", fmt.Sprintf("%s%s", h.ServerConfig.BindInterface, h.ServerConfig.Port)) @@ -1170,7 +1231,9 @@ func (h *MetadataServer) Start() error { go func() { if err := h.srv.Serve(l); err != nil && err != http.ErrServerClosed { - glog.Error("listen: %s\n", err) + // probably should use glog.Fatal() or propagate this err back to the main function + glog.Errorf("Critical error during Serve: : %s\n", err) + return } }()