From 990d3770cdb9793bff97404a3b19edd34c4ea27f Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Fri, 1 Jul 2022 09:15:36 -0400 Subject: [PATCH 01/15] Added new ingress with mTLS for gameserverapi --- cmd/gameserverapi/deploy.yaml | 2 +- cmd/gameserverapi/ingress-deploy.yaml | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 cmd/gameserverapi/ingress-deploy.yaml diff --git a/cmd/gameserverapi/deploy.yaml b/cmd/gameserverapi/deploy.yaml index 4fc1c11d..94b06288 100644 --- a/cmd/gameserverapi/deploy.yaml +++ b/cmd/gameserverapi/deploy.yaml @@ -56,4 +56,4 @@ spec: - protocol: TCP port: 5001 targetPort: 5001 - type: LoadBalancer \ No newline at end of file + type: ClusterIP \ No newline at end of file diff --git a/cmd/gameserverapi/ingress-deploy.yaml b/cmd/gameserverapi/ingress-deploy.yaml new file mode 100644 index 00000000..b807edc5 --- /dev/null +++ b/cmd/gameserverapi/ingress-deploy.yaml @@ -0,0 +1,22 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: thundernetes-gameserverapi-ingress + namespace: thundernetes-system + annotations: + nginx.ingress.kubernetes.io/auth-tls-verify-client: "on" + nginx.ingress.kubernetes.io/auth-tls-secret: "thundernetes-system/tls-certs" +spec: + ingressClassName: nginx + tls: + - secretName: tls-certs + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: thundernetes-gameserverapi + port: + number: 5001 \ No newline at end of file From 78e6cb6ca745a95e079901ba7f6238517212106a Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Fri, 1 Jul 2022 15:19:55 -0400 Subject: [PATCH 02/15] Refactored install file for gameserverapi with tls --- .../deployment/default/deploy.yaml | 2 +- .../deployment/secured/deploy_mtls.yaml | 82 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 cmd/gameserverapi/deployment/secured/deploy_mtls.yaml diff --git a/cmd/gameserverapi/deployment/default/deploy.yaml b/cmd/gameserverapi/deployment/default/deploy.yaml index 94b06288..4fc1c11d 100644 --- a/cmd/gameserverapi/deployment/default/deploy.yaml +++ b/cmd/gameserverapi/deployment/default/deploy.yaml @@ -56,4 +56,4 @@ spec: - protocol: TCP port: 5001 targetPort: 5001 - type: ClusterIP \ No newline at end of file + type: LoadBalancer \ No newline at end of file diff --git a/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml b/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml new file mode 100644 index 00000000..be3e8548 --- /dev/null +++ b/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml @@ -0,0 +1,82 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: thundernetes-gameserverapi + namespace: thundernetes-system + labels: + app: thundernetes-gameserverapi +spec: + selector: + matchLabels: + app: thundernetes-gameserverapi + replicas: 1 + template: + metadata: + labels: + app: thundernetes-gameserverapi + spec: + containers: + - image: thundernetes-gameserverapi:${IMAGE_TAG} + name: gameserverapi + imagePullPolicy: IfNotPresent + resources: + requests: + cpu: 100m + memory: 500Mi + limits: + cpu: 100m + memory: 500Mi + ports: + - containerPort: 5001 + hostPort: 5001 + livenessProbe: + httpGet: + path: /healthz + port: 5001 + initialDelaySeconds: 3 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /healthz + port: 5001 + initialDelaySeconds: 3 + periodSeconds: 10 + serviceAccountName: thundernetes-controller-manager + terminationGracePeriodSeconds: 10 +--- +apiVersion: v1 +kind: Service +metadata: + name: thundernetes-gameserverapi + namespace: thundernetes-system +spec: + selector: + app: thundernetes-gameserverapi + ports: + - protocol: TCP + port: 5001 + targetPort: 5001 + type: ClusterIP +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: thundernetes-gameserverapi-ingress + namespace: thundernetes-system + annotations: + nginx.ingress.kubernetes.io/auth-tls-verify-client: "on" + nginx.ingress.kubernetes.io/auth-tls-secret: "thundernetes-system/tls-certs" +spec: + ingressClassName: nginx + tls: + - secretName: tls-certs + rules: + - http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: thundernetes-gameserverapi + port: + number: 5001 \ No newline at end of file From 659e432aad9fe2c8a313a847f09263a47f253cb5 Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Fri, 1 Jul 2022 15:40:48 -0400 Subject: [PATCH 03/15] Added docs for installing gameserverapi with ingress and mtls --- cmd/gameserverapi/README.md | 50 +++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/cmd/gameserverapi/README.md b/cmd/gameserverapi/README.md index bc23726b..6294cb38 100755 --- a/cmd/gameserverapi/README.md +++ b/cmd/gameserverapi/README.md @@ -1,3 +1,53 @@ # GameServer API service (work in progress) GameServer API service is a RESTful API service that facilitates access to GameServerBuild/GameServer/GameServerDetail Custom Resources on your Kubernetes clusters. + +## Deploying the GameServer API with mutual TLS +It is possible to secure the GameServer API with mutual TLS using a Kubernetes Ingress, this way the Ingress will terminate any requests without the correct certificate. For this you have to create a Kubernetes Secret containing the server's private and public key, and the public key from the Certificate Authority (CA). For testing purposes, or for private use, you can be your own CA and self sign all your certificates. To do all of this you can follow the next steps: + +### Step 1: Install Thundernetes and the Nginx Ingress Controller on your cluster +``` +kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml + +kubectl apply -f https://raw.githubusercontent.com/PlayFab/thundernetes/main/installfiles/operator.yaml + +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/cloud/deploy.yaml +``` +### Step 2: Create a key pair to act as your Certificate Authority (CA) +``` +openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 1000 -nodes -subj '/CN=My Cert Authority' +``` + +### Step 3: Create key pairs for the server and for the client and sign them with the CA +``` +# create and sign the server keys +openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=Server' + +openssl x509 -req -sha256 -days 1000 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt + +# create and sign the client keys +openssl req -new -newkey rsa:4096 -keyout client.key -out client.csr -nodes -subj '/CN=Client' + +openssl x509 -req -sha256 -days 1000 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt +``` + +### Step 4: Create a Kubernetes Secret +``` +kubectl create secret generic -n thundernetes-system tls-certs --from-file=tls.crt=server.crt --from-file=tls.key=server.key --from-file=ca.crt=ca.crt +``` + +### Step 5: Deploy the Game Server API and an Ingress with your keys +We have bundled the definitions for the GameServer Deployment, Service, and Ingress in the ```secured/deploy_mtls.yaml``` file. You have to change the image inside the deployment and check the name of the Secret referenced in the Ingress matches the one you created. Then you just run: +``` +kubectl apply -f https://raw.githubusercontent.com/PlayFab/thundernetes/main/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml +``` + +### Connect to the Game Server API +Now the Game Server API is exposed through the Ingress, to connect to it you have to get the Ingress' external IP, you can do this with this command: +``` +kubectl get ingress thundernetes-gameserverapi-ingress -n thundernetes-system +``` +The Ingress may take a minute before getting an IP, if you're running this locally it won't ever get one, but you can use port forwarding instead. Finally try a simple GET request providing the client keys to test that API is working: +``` +curl https://{ingress_IP}/api/v1/gameserverbuilds --cert client.crt --key client.key -k +``` From c4e79ec680f6af9e434e4e6d31c061489b10a0e5 Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Fri, 1 Jul 2022 15:46:22 -0400 Subject: [PATCH 04/15] Fixed typo in docs --- cmd/gameserverapi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gameserverapi/README.md b/cmd/gameserverapi/README.md index 6294cb38..f59e5199 100755 --- a/cmd/gameserverapi/README.md +++ b/cmd/gameserverapi/README.md @@ -47,7 +47,7 @@ Now the Game Server API is exposed through the Ingress, to connect to it you hav ``` kubectl get ingress thundernetes-gameserverapi-ingress -n thundernetes-system ``` -The Ingress may take a minute before getting an IP, if you're running this locally it won't ever get one, but you can use port forwarding instead. Finally try a simple GET request providing the client keys to test that API is working: +The Ingress may take a minute before getting an IP, if you're running this locally it won't ever get one, but you can use port forwarding instead. Finally try a simple GET request providing the client keys to test that the API is working: ``` curl https://{ingress_IP}/api/v1/gameserverbuilds --cert client.crt --key client.key -k ``` From 56d67c70dd8d987f906acd376a34cb50dbf77f2c Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Fri, 1 Jul 2022 16:14:45 -0400 Subject: [PATCH 05/15] Changed a command in the docs --- cmd/gameserverapi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gameserverapi/README.md b/cmd/gameserverapi/README.md index f59e5199..c43b3d71 100755 --- a/cmd/gameserverapi/README.md +++ b/cmd/gameserverapi/README.md @@ -39,7 +39,7 @@ kubectl create secret generic -n thundernetes-system tls-certs --from-file=tls.c ### Step 5: Deploy the Game Server API and an Ingress with your keys We have bundled the definitions for the GameServer Deployment, Service, and Ingress in the ```secured/deploy_mtls.yaml``` file. You have to change the image inside the deployment and check the name of the Secret referenced in the Ingress matches the one you created. Then you just run: ``` -kubectl apply -f https://raw.githubusercontent.com/PlayFab/thundernetes/main/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml +kubectl apply -f [path to deploy_mtls.yaml] ``` ### Connect to the Game Server API From bc2bb2565d5f3df88c8dc97d634d50170a7f869f Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Fri, 1 Jul 2022 16:18:12 -0400 Subject: [PATCH 06/15] Changed file path in docs --- cmd/gameserverapi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gameserverapi/README.md b/cmd/gameserverapi/README.md index c43b3d71..14f10837 100755 --- a/cmd/gameserverapi/README.md +++ b/cmd/gameserverapi/README.md @@ -37,7 +37,7 @@ kubectl create secret generic -n thundernetes-system tls-certs --from-file=tls.c ``` ### Step 5: Deploy the Game Server API and an Ingress with your keys -We have bundled the definitions for the GameServer Deployment, Service, and Ingress in the ```secured/deploy_mtls.yaml``` file. You have to change the image inside the deployment and check the name of the Secret referenced in the Ingress matches the one you created. Then you just run: +We have bundled the definitions for the GameServer Deployment, Service, and Ingress in the ```deployment/secured/deploy_mtls.yaml``` file. You have to change the image inside the deployment and check the name of the Secret referenced in the Ingress matches the one you created. Then you just run: ``` kubectl apply -f [path to deploy_mtls.yaml] ``` From 52fada834b7b95a2acf7285bfa7e7d0e6efe9784 Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Fri, 1 Jul 2022 16:34:50 -0400 Subject: [PATCH 07/15] Changed brackets in docs --- cmd/gameserverapi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gameserverapi/README.md b/cmd/gameserverapi/README.md index 14f10837..55eaf203 100755 --- a/cmd/gameserverapi/README.md +++ b/cmd/gameserverapi/README.md @@ -39,7 +39,7 @@ kubectl create secret generic -n thundernetes-system tls-certs --from-file=tls.c ### Step 5: Deploy the Game Server API and an Ingress with your keys We have bundled the definitions for the GameServer Deployment, Service, and Ingress in the ```deployment/secured/deploy_mtls.yaml``` file. You have to change the image inside the deployment and check the name of the Secret referenced in the Ingress matches the one you created. Then you just run: ``` -kubectl apply -f [path to deploy_mtls.yaml] +kubectl apply -f {path to deploy_mtls.yaml} ``` ### Connect to the Game Server API From 839ad03498fe950c5e3767babdaf4ef837788787 Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Fri, 1 Jul 2022 16:36:02 -0400 Subject: [PATCH 08/15] Delete unused yaml file --- cmd/gameserverapi/ingress-deploy.yaml | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 cmd/gameserverapi/ingress-deploy.yaml diff --git a/cmd/gameserverapi/ingress-deploy.yaml b/cmd/gameserverapi/ingress-deploy.yaml deleted file mode 100644 index b807edc5..00000000 --- a/cmd/gameserverapi/ingress-deploy.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: thundernetes-gameserverapi-ingress - namespace: thundernetes-system - annotations: - nginx.ingress.kubernetes.io/auth-tls-verify-client: "on" - nginx.ingress.kubernetes.io/auth-tls-secret: "thundernetes-system/tls-certs" -spec: - ingressClassName: nginx - tls: - - secretName: tls-certs - rules: - - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: thundernetes-gameserverapi - port: - number: 5001 \ No newline at end of file From 0ae5953626aed3ba29dd8cb4e812b8a2a1f67ce2 Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Fri, 8 Jul 2022 09:30:37 -0400 Subject: [PATCH 09/15] Trying some annotations --- cmd/gameserverapi/deployment/secured/deploy_mtls.yaml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml b/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml index be3e8548..3f64e195 100644 --- a/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml +++ b/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml @@ -16,7 +16,7 @@ spec: app: thundernetes-gameserverapi spec: containers: - - image: thundernetes-gameserverapi:${IMAGE_TAG} + - image: ghcr.io/playfab/thundernetes-gameserverapi:0.4.1 name: gameserverapi imagePullPolicy: IfNotPresent resources: @@ -64,12 +64,17 @@ metadata: name: thundernetes-gameserverapi-ingress namespace: thundernetes-system annotations: + kubernetes.io/ingress.class: nginx + nginx.ingress.kubernetes.io/ssl-redirect: "true" + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" nginx.ingress.kubernetes.io/auth-tls-verify-client: "on" - nginx.ingress.kubernetes.io/auth-tls-secret: "thundernetes-system/tls-certs" + nginx.ingress.kubernetes.io/auth-tls-secret: "thundernetes-system/ca-secret" + # nginx.ingress.kubernetes.io/enable-cors: "true" + # nginx.ingress.kubernetes.io/cors-allow-credentials: "true" spec: ingressClassName: nginx tls: - - secretName: tls-certs + - secretName: tls-secret rules: - http: paths: From 15a4a32538a661a2d039fb1477ce17d9993db4ec Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Tue, 12 Jul 2022 13:29:33 -0400 Subject: [PATCH 10/15] Moved the docs to the HowTo's, fixed deploy yaml --- cmd/gameserverapi/README.md | 50 ----------- .../deployment/secured/deploy_mtls.yaml | 9 +- docs/howtos/serviceingress.md | 88 +++++++++++++++++++ 3 files changed, 93 insertions(+), 54 deletions(-) create mode 100644 docs/howtos/serviceingress.md diff --git a/cmd/gameserverapi/README.md b/cmd/gameserverapi/README.md index 55eaf203..bc23726b 100755 --- a/cmd/gameserverapi/README.md +++ b/cmd/gameserverapi/README.md @@ -1,53 +1,3 @@ # GameServer API service (work in progress) GameServer API service is a RESTful API service that facilitates access to GameServerBuild/GameServer/GameServerDetail Custom Resources on your Kubernetes clusters. - -## Deploying the GameServer API with mutual TLS -It is possible to secure the GameServer API with mutual TLS using a Kubernetes Ingress, this way the Ingress will terminate any requests without the correct certificate. For this you have to create a Kubernetes Secret containing the server's private and public key, and the public key from the Certificate Authority (CA). For testing purposes, or for private use, you can be your own CA and self sign all your certificates. To do all of this you can follow the next steps: - -### Step 1: Install Thundernetes and the Nginx Ingress Controller on your cluster -``` -kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml - -kubectl apply -f https://raw.githubusercontent.com/PlayFab/thundernetes/main/installfiles/operator.yaml - -kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/cloud/deploy.yaml -``` -### Step 2: Create a key pair to act as your Certificate Authority (CA) -``` -openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 1000 -nodes -subj '/CN=My Cert Authority' -``` - -### Step 3: Create key pairs for the server and for the client and sign them with the CA -``` -# create and sign the server keys -openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN=Server' - -openssl x509 -req -sha256 -days 1000 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt - -# create and sign the client keys -openssl req -new -newkey rsa:4096 -keyout client.key -out client.csr -nodes -subj '/CN=Client' - -openssl x509 -req -sha256 -days 1000 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt -``` - -### Step 4: Create a Kubernetes Secret -``` -kubectl create secret generic -n thundernetes-system tls-certs --from-file=tls.crt=server.crt --from-file=tls.key=server.key --from-file=ca.crt=ca.crt -``` - -### Step 5: Deploy the Game Server API and an Ingress with your keys -We have bundled the definitions for the GameServer Deployment, Service, and Ingress in the ```deployment/secured/deploy_mtls.yaml``` file. You have to change the image inside the deployment and check the name of the Secret referenced in the Ingress matches the one you created. Then you just run: -``` -kubectl apply -f {path to deploy_mtls.yaml} -``` - -### Connect to the Game Server API -Now the Game Server API is exposed through the Ingress, to connect to it you have to get the Ingress' external IP, you can do this with this command: -``` -kubectl get ingress thundernetes-gameserverapi-ingress -n thundernetes-system -``` -The Ingress may take a minute before getting an IP, if you're running this locally it won't ever get one, but you can use port forwarding instead. Finally try a simple GET request providing the client keys to test that the API is working: -``` -curl https://{ingress_IP}/api/v1/gameserverbuilds --cert client.crt --key client.key -k -``` diff --git a/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml b/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml index 3f64e195..181a0710 100644 --- a/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml +++ b/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml @@ -68,15 +68,16 @@ metadata: nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" nginx.ingress.kubernetes.io/auth-tls-verify-client: "on" - nginx.ingress.kubernetes.io/auth-tls-secret: "thundernetes-system/ca-secret" - # nginx.ingress.kubernetes.io/enable-cors: "true" - # nginx.ingress.kubernetes.io/cors-allow-credentials: "true" + nginx.ingress.kubernetes.io/auth-tls-secret: "thundernetes-system/tls-secret" spec: ingressClassName: nginx tls: + - hosts: + - {your host} - secretName: tls-secret rules: - - http: + - host: {your host} + http: paths: - path: / pathType: Prefix diff --git a/docs/howtos/serviceingress.md b/docs/howtos/serviceingress.md new file mode 100644 index 00000000..a0c702fe --- /dev/null +++ b/docs/howtos/serviceingress.md @@ -0,0 +1,88 @@ +--- +layout: default +title: Protect your Services using an Ingress +parent: How to's +nav_order: 11 +--- +# Protect your Services using an Ingress +It is possible to secure any service in the cluster using a Kubernetes [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/), this way it can terminate any requests that don't have the right credentials. Kubernetes doesn't have an Ingress implementation out of the box, so you have to choose an [Ingress Controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/) to install. An Ingress can provide multiple ways to authenticate requests, depending on the implementation, for example, the [Nginx Ingress Controller](https://kubernetes.github.io/ingress-nginx/deploy/) allows you to use: basic authentication, mutual TLS (mTLS) or use external authentication services. In the following section we show how to use an Ingress to enable mTLS for the Game Server API. + +## Enabling mTLS for the Game Server API + +When you deploy an Ingress you can use annotations to enable the authentication of both the server and the client, all of this will happen at the Ingress level, so you don't have to change any code in the service. Note that this needs you to have a domain you can use for your service. For this, you have to create a Kubernetes Secret containing the server's private and public key, and the public key from the Certificate Authority (CA). For testing purposes, or for private use, you can create your own CA and use it to sign all your certificates. To do all of this you can follow the next steps: + +### Step 1: Install Thundernetes and the Nginx Ingress Controller on your cluster +``` +kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml + +kubectl apply -f https://raw.githubusercontent.com/PlayFab/thundernetes/main/installfiles/operator.yaml + +kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/cloud/deploy.yaml +``` +### Step 2: Create a key pair to act as your Certificate Authority (CA) +``` +openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 1000 -nodes -subj '/CN=My Cert Authority' +``` + +### Step 3: Create key pairs for the server and for the client and sign them with the CA +``` +# create and sign the server keys +openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN={the host of your server}' -addext "subjectAltName=DNS:{the host of your server}" + +openssl x509 -req -sha256 -days 1000 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt + +# create and sign the client keys +openssl req -new -newkey rsa:4096 -keyout client.key -out client.csr -nodes -subj '/CN=Client' + +openssl x509 -req -sha256 -days 1000 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 02 -out client.crt +``` + +### Step 4: Create a Kubernetes Secret +``` +kubectl create secret generic -n thundernetes-system tls-certs --from-file=tls.crt=server.crt --from-file=tls.key=server.key --from-file=ca.crt=ca.crt +``` + +### Step 5: Deploy the Service and the Ingress +We have bundled the definitions to deploy the GameServer API in the [deployment/secured/deploy_mtls.yaml](https://github.com/PlayFab/thundernetes/blob/main/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml) file , it includes the Deployment, the Service, and the Ingress needed for the mTLS to work. You have to check the name of the Secret referenced in the Ingress matches the one you created, and also add the host values required. Then you just run: +``` +kubectl apply -f {path to deploy_mtls.yaml} +``` + +### Setp 6: Connect to the Game Server API +Now the Game Server API is exposed through the Ingress, to connect to it you have to get the Ingress' external IP, you can do this with this command: +``` +kubectl get ingress thundernetes-gameserverapi-ingress -n thundernetes-system +``` +The Ingress may take a minute before getting an IP, if you're running this locally it won't ever get one, but you can use port forwarding instead. Finally you can try a simple GET request providing the client keys to test that the API is working, note that you will have to add the public certificate of your CA to your trusted root certificates: +``` +curl https://{ingress_IP}/api/v1/gameserverbuilds --cert client.crt --key client.key +``` +Or, you can also skip the validation on the client side and only check that the server is verifying the client certificates, adding the ```-k``` or ```--insecure``` option: +``` +curl https://{ingress_IP}/api/v1/gameserverbuilds --cert client.crt --key client.key -k +``` + +### Extra: Using an IP instead of a domain +Although it is not officially supported, you can use this configuration for an IP instead of a domain. The first thing to do is adding the IP of the ingress as a CN and SAN when you generate the server certificates: +``` +# get the IP of the ingress, it's the EXTERNAL-IP of the LoadBalancer +kubectl get service -n ingress-nginx +``` +``` +# create and sign the server keys, using the IP +openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN={the IP of your server}' -addext "subjectAltName=IP:{the IP of your server}" + +openssl x509 -req -sha256 -days 1000 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt +``` +Then, you have to remove the ```hosts``` and ```host``` fields on the deploy yaml located at [deployment/secured/deploy_mtls.yaml](https://github.com/PlayFab/thundernetes/blob/main/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml) and then deploy. What will happen now is that the Ingress won't be able to resolve which TLS certificates are the from the server, because it uses the host fields for that, but you can bypass this by adding the ```default-ssl-certificate``` option with your certificates as a fallback, for this, you have edit the Ingress Controller with the following line: +``` +kubectl edit -n ingress-nginx deployment.apps/ingress-nginx-controller +``` +Then you have to add the option in under the following field, the value to add is the {namespace}/{secret} of the one you created: +```yaml +spec: + container: + args: + - ... + - --default-ssl-certificate=thundernetes-system/tls-secret +``` From e833a5bdebfcb9eb357384c0e5ca90bb05a938f1 Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Tue, 12 Jul 2022 13:35:49 -0400 Subject: [PATCH 11/15] Spacing --- docs/howtos/serviceingress.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/howtos/serviceingress.md b/docs/howtos/serviceingress.md index a0c702fe..86c790ae 100644 --- a/docs/howtos/serviceingress.md +++ b/docs/howtos/serviceingress.md @@ -4,7 +4,9 @@ title: Protect your Services using an Ingress parent: How to's nav_order: 11 --- + # Protect your Services using an Ingress + It is possible to secure any service in the cluster using a Kubernetes [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/), this way it can terminate any requests that don't have the right credentials. Kubernetes doesn't have an Ingress implementation out of the box, so you have to choose an [Ingress Controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/) to install. An Ingress can provide multiple ways to authenticate requests, depending on the implementation, for example, the [Nginx Ingress Controller](https://kubernetes.github.io/ingress-nginx/deploy/) allows you to use: basic authentication, mutual TLS (mTLS) or use external authentication services. In the following section we show how to use an Ingress to enable mTLS for the Game Server API. ## Enabling mTLS for the Game Server API @@ -19,12 +21,15 @@ kubectl apply -f https://raw.githubusercontent.com/PlayFab/thundernetes/main/ins kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/cloud/deploy.yaml ``` + ### Step 2: Create a key pair to act as your Certificate Authority (CA) + ``` openssl req -x509 -sha256 -newkey rsa:4096 -keyout ca.key -out ca.crt -days 1000 -nodes -subj '/CN=My Cert Authority' ``` ### Step 3: Create key pairs for the server and for the client and sign them with the CA + ``` # create and sign the server keys openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN={the host of your server}' -addext "subjectAltName=DNS:{the host of your server}" @@ -38,47 +43,63 @@ openssl x509 -req -sha256 -days 1000 -in client.csr -CA ca.crt -CAkey ca.key -se ``` ### Step 4: Create a Kubernetes Secret + ``` kubectl create secret generic -n thundernetes-system tls-certs --from-file=tls.crt=server.crt --from-file=tls.key=server.key --from-file=ca.crt=ca.crt ``` ### Step 5: Deploy the Service and the Ingress + We have bundled the definitions to deploy the GameServer API in the [deployment/secured/deploy_mtls.yaml](https://github.com/PlayFab/thundernetes/blob/main/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml) file , it includes the Deployment, the Service, and the Ingress needed for the mTLS to work. You have to check the name of the Secret referenced in the Ingress matches the one you created, and also add the host values required. Then you just run: + ``` kubectl apply -f {path to deploy_mtls.yaml} ``` -### Setp 6: Connect to the Game Server API +### Step 6: Connect to the Game Server API + Now the Game Server API is exposed through the Ingress, to connect to it you have to get the Ingress' external IP, you can do this with this command: + ``` kubectl get ingress thundernetes-gameserverapi-ingress -n thundernetes-system ``` + The Ingress may take a minute before getting an IP, if you're running this locally it won't ever get one, but you can use port forwarding instead. Finally you can try a simple GET request providing the client keys to test that the API is working, note that you will have to add the public certificate of your CA to your trusted root certificates: + ``` curl https://{ingress_IP}/api/v1/gameserverbuilds --cert client.crt --key client.key ``` + Or, you can also skip the validation on the client side and only check that the server is verifying the client certificates, adding the ```-k``` or ```--insecure``` option: + ``` curl https://{ingress_IP}/api/v1/gameserverbuilds --cert client.crt --key client.key -k ``` ### Extra: Using an IP instead of a domain + Although it is not officially supported, you can use this configuration for an IP instead of a domain. The first thing to do is adding the IP of the ingress as a CN and SAN when you generate the server certificates: + ``` # get the IP of the ingress, it's the EXTERNAL-IP of the LoadBalancer kubectl get service -n ingress-nginx ``` + ``` # create and sign the server keys, using the IP openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN={the IP of your server}' -addext "subjectAltName=IP:{the IP of your server}" openssl x509 -req -sha256 -days 1000 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt ``` + Then, you have to remove the ```hosts``` and ```host``` fields on the deploy yaml located at [deployment/secured/deploy_mtls.yaml](https://github.com/PlayFab/thundernetes/blob/main/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml) and then deploy. What will happen now is that the Ingress won't be able to resolve which TLS certificates are the from the server, because it uses the host fields for that, but you can bypass this by adding the ```default-ssl-certificate``` option with your certificates as a fallback, for this, you have edit the Ingress Controller with the following line: + ``` kubectl edit -n ingress-nginx deployment.apps/ingress-nginx-controller ``` + Then you have to add the option in under the following field, the value to add is the {namespace}/{secret} of the one you created: + ```yaml spec: container: From 2261276375903d3f3c3afc9a409c144ef2138759 Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Tue, 12 Jul 2022 15:04:14 -0400 Subject: [PATCH 12/15] Removed the section about using an IP for the Ingress --- docs/howtos/serviceingress.md | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/docs/howtos/serviceingress.md b/docs/howtos/serviceingress.md index 86c790ae..ccf6b236 100644 --- a/docs/howtos/serviceingress.md +++ b/docs/howtos/serviceingress.md @@ -75,35 +75,3 @@ Or, you can also skip the validation on the client side and only check that the ``` curl https://{ingress_IP}/api/v1/gameserverbuilds --cert client.crt --key client.key -k ``` - -### Extra: Using an IP instead of a domain - -Although it is not officially supported, you can use this configuration for an IP instead of a domain. The first thing to do is adding the IP of the ingress as a CN and SAN when you generate the server certificates: - -``` -# get the IP of the ingress, it's the EXTERNAL-IP of the LoadBalancer -kubectl get service -n ingress-nginx -``` - -``` -# create and sign the server keys, using the IP -openssl req -new -newkey rsa:4096 -keyout server.key -out server.csr -nodes -subj '/CN={the IP of your server}' -addext "subjectAltName=IP:{the IP of your server}" - -openssl x509 -req -sha256 -days 1000 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt -``` - -Then, you have to remove the ```hosts``` and ```host``` fields on the deploy yaml located at [deployment/secured/deploy_mtls.yaml](https://github.com/PlayFab/thundernetes/blob/main/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml) and then deploy. What will happen now is that the Ingress won't be able to resolve which TLS certificates are the from the server, because it uses the host fields for that, but you can bypass this by adding the ```default-ssl-certificate``` option with your certificates as a fallback, for this, you have edit the Ingress Controller with the following line: - -``` -kubectl edit -n ingress-nginx deployment.apps/ingress-nginx-controller -``` - -Then you have to add the option in under the following field, the value to add is the {namespace}/{secret} of the one you created: - -```yaml -spec: - container: - args: - - ... - - --default-ssl-certificate=thundernetes-system/tls-secret -``` From 37fa2ec069430817eb6f0e50dceafd5499404369 Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Tue, 12 Jul 2022 15:08:15 -0400 Subject: [PATCH 13/15] Minor corrections for pr --- cmd/gameserverapi/deployment/secured/deploy_mtls.yaml | 6 +++--- docs/howtos/serviceingress.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml b/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml index 181a0710..4dd924c3 100644 --- a/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml +++ b/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml @@ -16,7 +16,7 @@ spec: app: thundernetes-gameserverapi spec: containers: - - image: ghcr.io/playfab/thundernetes-gameserverapi:0.4.1 + - image: ghcr.io/playfab/thundernetes-gameserverapi:${IMAGE_TAG} name: gameserverapi imagePullPolicy: IfNotPresent resources: @@ -73,10 +73,10 @@ spec: ingressClassName: nginx tls: - hosts: - - {your host} + - ${HOST} - secretName: tls-secret rules: - - host: {your host} + - host: ${HOST} http: paths: - path: / diff --git a/docs/howtos/serviceingress.md b/docs/howtos/serviceingress.md index ccf6b236..9a7363eb 100644 --- a/docs/howtos/serviceingress.md +++ b/docs/howtos/serviceingress.md @@ -50,7 +50,7 @@ kubectl create secret generic -n thundernetes-system tls-certs --from-file=tls.c ### Step 5: Deploy the Service and the Ingress -We have bundled the definitions to deploy the GameServer API in the [deployment/secured/deploy_mtls.yaml](https://github.com/PlayFab/thundernetes/blob/main/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml) file , it includes the Deployment, the Service, and the Ingress needed for the mTLS to work. You have to check the name of the Secret referenced in the Ingress matches the one you created, and also add the host values required. Then you just run: +We have bundled the definitions to deploy the GameServer API in the [deployment/secured/deploy_mtls.yaml](https://github.com/PlayFab/thundernetes/blob/main/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml) file, it includes the Deployment, the Service, and the Ingress needed for the mTLS to work. You have to check the name of the Secret referenced in the Ingress matches the one you created, and also add the host values required. Then you just run: ``` kubectl apply -f {path to deploy_mtls.yaml} From 33103dbdb5346c950b161c471ce276236bd95d71 Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Tue, 12 Jul 2022 15:10:18 -0400 Subject: [PATCH 14/15] Added info about replacing values in the yaml --- docs/howtos/serviceingress.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/howtos/serviceingress.md b/docs/howtos/serviceingress.md index 9a7363eb..5940d75e 100644 --- a/docs/howtos/serviceingress.md +++ b/docs/howtos/serviceingress.md @@ -50,7 +50,7 @@ kubectl create secret generic -n thundernetes-system tls-certs --from-file=tls.c ### Step 5: Deploy the Service and the Ingress -We have bundled the definitions to deploy the GameServer API in the [deployment/secured/deploy_mtls.yaml](https://github.com/PlayFab/thundernetes/blob/main/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml) file, it includes the Deployment, the Service, and the Ingress needed for the mTLS to work. You have to check the name of the Secret referenced in the Ingress matches the one you created, and also add the host values required. Then you just run: +We have bundled the definitions to deploy the GameServer API in the [deployment/secured/deploy_mtls.yaml](https://github.com/PlayFab/thundernetes/blob/main/cmd/gameserverapi/deployment/secured/deploy_mtls.yaml) file, it includes the Deployment, the Service, and the Ingress needed for the mTLS to work. You have to check the name of the Secret referenced in the Ingress matches the one you created, replace the ```${IMAGE_TAG}``` for the current release, and also replace the ```${HOST}``` values for your domain. Then you just run: ``` kubectl apply -f {path to deploy_mtls.yaml} From 5997ce304e0bd009acd0bfe191382da5bb38b596 Mon Sep 17 00:00:00 2001 From: Javier Morales Date: Tue, 12 Jul 2022 15:12:14 -0400 Subject: [PATCH 15/15] Added link about port forwarding in Kubernetes --- docs/howtos/serviceingress.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/howtos/serviceingress.md b/docs/howtos/serviceingress.md index 5940d75e..1159c8d4 100644 --- a/docs/howtos/serviceingress.md +++ b/docs/howtos/serviceingress.md @@ -64,7 +64,7 @@ Now the Game Server API is exposed through the Ingress, to connect to it you hav kubectl get ingress thundernetes-gameserverapi-ingress -n thundernetes-system ``` -The Ingress may take a minute before getting an IP, if you're running this locally it won't ever get one, but you can use port forwarding instead. Finally you can try a simple GET request providing the client keys to test that the API is working, note that you will have to add the public certificate of your CA to your trusted root certificates: +The Ingress may take a minute before getting an IP, if you're running this locally it won't ever get one, but you can use [port forwarding](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/) instead. Finally you can try a simple GET request providing the client keys to test that the API is working, note that you will have to add the public certificate of your CA to your trusted root certificates: ``` curl https://{ingress_IP}/api/v1/gameserverbuilds --cert client.crt --key client.key