Skip to content

Commit

Permalink
Merge pull request #10 from akrejcir/use-sa-for-token
Browse files Browse the repository at this point in the history
feat: Use ServiceAccount to generate token
  • Loading branch information
kubevirt-bot authored Jul 20, 2023
2 parents 9038e34 + a99b0f2 commit ea3ebe3
Show file tree
Hide file tree
Showing 38 changed files with 1,068 additions and 3,403 deletions.
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# VM Console Proxy

Proxy that provides access to the VNC console of a Kubevirt VM.
It provides an endpoint to generate time limited tokens that are then used to access VNC.

It can generate time limited tokens that are then used to access VNC.
**Note:** This project no longer provides VNC proxy functionality, so the project name should be changed in the future.

## Installation

Expand All @@ -11,10 +11,9 @@ The [SSP operator](https://github.com/kubevirt/ssp-operator) can be configured t
a Route to expose it to the external network.

### Without SSP operator
VM Console Proxy needs to be deployed in the same namespace as KubeVirt.
To deploy the latest version, use the following command:
```bash
kubectl apply -n ${KUBEVIRT_NAMESPACE} -f "https://github.com/kubevirt/vm-console-proxy/releases/latest/download/vm-console-proxy.yaml"
kubectl apply -f "https://github.com/kubevirt/vm-console-proxy/releases/latest/download/vm-console-proxy.yaml"
```

## API
Expand All @@ -32,7 +31,7 @@ apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: vm-console
namespace: kubevirt
namespace: ${VM_CONSOLE_PROXY_NAMESPACE}
spec:
rules:
- host: ${HOSTNAME}
Expand Down
13 changes: 0 additions & 13 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,3 @@ kubernetes API. It can be obtained using:
```bash
KUBERNETES_USER_TOKEN=$(oc whoami -t)
```

## Accessing VNC
VNC can be accessed using websocket on this endpoint:
```
/api/v1alpha1/${VMI_NAMESPACE}/${VMI_NAME}/vnc
```

#### Subprotocol
- `base64url.bearer.authorization.k8s.io.${TOKEN}` - Is used for authorization. The `TOKEN`
variable is a token generated by the `/token` endpoint.

### Example
The `example-client` subdirectory shows how to access this endpoint using the [noVNC](https://novnc.com/info.html) JavaScript library.
7 changes: 5 additions & 2 deletions example-client/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Example VNC client

**This example client currently does not work. It will be fixed in the future.**

This directory contains an example page that uses noVNC library
to connect to the `vn-console-proxy` running on a cluster.

Expand All @@ -9,14 +11,15 @@ make serve-client
```

The client page takes these URL parameters:
- `host` - Hostname for the route. For CRC it will be: `vm-console-kubevirt.apps-crc.testing`
- `host` - Hostname for kubevirt API. For CRC it will be: `api.crc.testing`.
- `port` - Port for kubevirt API. For CRC it will be `6443`.
- `namspace` - Namespace where the VM is.
- `name` - Name of the VM.
- `token` - Token generated using the `/token` endpoint.

For example, the following URL will point the client to a VM after substituting variables:
```
http://localhost:8000/?host=vm-console-kubevirt.apps-crc.testing&namespace=${VM_NAMESPACE}&name=${VM_NAME}&token=${TOKEN}
http://localhost:8000/?host=api.crc.testing&port=6443&namespace=${VM_NAMESPACE}&name=${VM_NAME}&token=${TOKEN}
```

**Note:** If the browser does not trust the TLS certificate from the cluster, only a generic
Expand Down
3 changes: 1 addition & 2 deletions example-client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@
.onclick = sendCtrlAltDel;

// Read parameters specified in the URL query string
// By default, use the host and port of server that served this file
const host = readQueryVariable('host');
let port = readQueryVariable('port');

Expand All @@ -153,7 +152,7 @@
if(port) {
url += ':' + port;
}
url += '/api/v1alpha1/' + vmNamespace + '/' + vmName + '/vnc'
url += '/apis/subresources.kubevirt.io/v1/namespaces/' + vmNamespace + '/virtualmachineinstances/'+ vmName +'/vnc'

// Creating a new RFB object will start a new connection
rfb = new RFB(
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ require (
github.com/golang-jwt/jwt/v4 v4.4.3
github.com/golang/mock v1.5.0
github.com/gorilla/websocket v1.5.0
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed
github.com/onsi/ginkgo/v2 v2.6.1
github.com/onsi/gomega v1.24.2
github.com/openshift/api v0.0.0-20220504105152-6f735e7109c8
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -581,8 +581,6 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed h1:FI2NIv6fpef6BQl2u3IZX/Cj20tfypRF4yd+uaHOMtI=
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
Expand Down
38 changes: 38 additions & 0 deletions manifests/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,48 @@ rules:
- kubevirt.io
resources:
- virtualmachineinstances
- virtualmachines
verbs:
- get
- list
- watch
- apiGroups:
- subresources.kubevirt.io
resources:
- virtualmachineinstances/vnc
verbs:
- get
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- get
- list
- watch
- create
- update
- delete
- patch
- apiGroups:
- ""
resources:
- serviceaccounts/token
verbs:
- create
- apiGroups:
- rbac.authorization.k8s.io
resources:
- roles
- rolebindings
verbs:
- get
- list
- watch
- create
- update
- delete
- patch
- apiGroups:
- authentication.k8s.io
resources:
Expand Down
37 changes: 3 additions & 34 deletions pkg/console/console.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@ import (
"path/filepath"

"github.com/emicklei/go-restful/v3"
"k8s.io/client-go/metadata"
"kubevirt.io/client-go/kubecli"
"kubevirt.io/client-go/log"

"github.com/kubevirt/vm-console-proxy/pkg/console/dialer"
"github.com/kubevirt/vm-console-proxy/pkg/console/service"
"github.com/kubevirt/vm-console-proxy/pkg/console/tlsconfig"
"github.com/kubevirt/vm-console-proxy/pkg/token"
)

const (
Expand All @@ -35,12 +33,6 @@ func Run() error {
return err
}

metadataClient, err := metadata.NewForConfig(cli.Config())
if err != nil {
return err

}

tlsConfigWatch := tlsconfig.NewWatch(
filepath.Join(configDir, TlsProfileFile),
serviceCertPath,
Expand All @@ -55,23 +47,7 @@ func Run() error {
log.Log.Errorf("Error running TLS config watch: %s", err)
}()

tokenKeyCache := token.NewKeyCache()
handlers := &service{
kubevirtClient: cli,
metadataClient: metadataClient,
websocketDialer: dialer.New(),
getTokenSigningKey: func() ([]byte, error) {
tlsConfig, err := tlsConfigWatch.GetConfig()
if err != nil {
return nil, err
}
tokenKey, err := tokenKeyCache.Get(tlsConfig.Certificates[0].PrivateKey)
if err != nil {
return nil, err
}
return tokenKey, nil
},
}
handlers := service.NewService(cli)

restful.Add(webService(handlers))
cors := restful.CrossOriginResourceSharing{
Expand All @@ -98,7 +74,7 @@ func Run() error {
return server.ListenAndServeTLS("", "")
}

func webService(handlers *service) *restful.WebService {
func webService(handlers service.Service) *restful.WebService {
ws := new(restful.WebService)
ws.Route(ws.GET(urlPathPrefix + "/token").
To(handlers.TokenHandler).
Expand All @@ -108,12 +84,5 @@ func webService(handlers *service) *restful.WebService {
Param(ws.PathParameter("name", "name").Required(true)).
Param(ws.QueryParameter("duration", "duration")))

ws.Route(ws.GET(urlPathPrefix + "/vnc").
To(handlers.VncHandler).
Doc("vnc connection").
Operation("vnc").
Param(ws.PathParameter("namespace", "namespace").Required(true)).
Param(ws.PathParameter("name", "name").Required(true)))

return ws
}
47 changes: 0 additions & 47 deletions pkg/console/dialer/dialer.go

This file was deleted.

Loading

0 comments on commit ea3ebe3

Please sign in to comment.