Skip to content

Commit

Permalink
Filter resources before returning to the client
Browse files Browse the repository at this point in the history
Filter resources returned from the REST and WebSocket APIs before
returning them to the client.

Ensure the status code is returned correctly.
  • Loading branch information
AlanGreene authored and tekton-robot committed May 12, 2020
1 parent 5a1b822 commit 410c7ca
Show file tree
Hide file tree
Showing 17 changed files with 193 additions and 101 deletions.
2 changes: 1 addition & 1 deletion base/200-clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ rules:
resources: ["pods/log", "namespaces", "events"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["secrets", "configmaps"]
resources: ["configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: ["extensions", "apps"]
resources: ["deployments"]
Expand Down
15 changes: 14 additions & 1 deletion overlays/full-fat/cluster-role-patch-json.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
apiGroups:
- ""
resources:
- secrets
- configmaps
verbs:
- create
Expand Down Expand Up @@ -122,3 +121,17 @@
- delete
- patch
- add
- op: add
path: /rules/9
value:
apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- watch
- create
- update
- delete
2 changes: 1 addition & 1 deletion pkg/controllers/kubernetes/extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package kubernetes

import (
"github.com/tektoncd/dashboard/pkg/broadcaster"
"github.com/tektoncd/dashboard/pkg/controllers/utils"
"github.com/tektoncd/dashboard/pkg/endpoints"
"github.com/tektoncd/dashboard/pkg/logging"
"github.com/tektoncd/dashboard/pkg/router"
"github.com/tektoncd/dashboard/pkg/utils"
v1 "k8s.io/api/core/v1"
k8sinformer "k8s.io/client-go/informers"
"k8s.io/client-go/tools/cache"
Expand Down
1 change: 1 addition & 0 deletions pkg/controllers/kubernetes/namespaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ func NewNamespaceController(sharedK8sInformerFactory k8sinformer.SharedInformerF
broadcaster.NamespaceCreated,
broadcaster.NamespaceUpdated,
broadcaster.NamespaceDeleted,
nil,
)
}
6 changes: 4 additions & 2 deletions pkg/controllers/kubernetes/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package kubernetes

import (
"github.com/tektoncd/dashboard/pkg/broadcaster"
"github.com/tektoncd/dashboard/pkg/controllers/utils"
controllerUtils "github.com/tektoncd/dashboard/pkg/controllers/utils"
"github.com/tektoncd/dashboard/pkg/logging"
"github.com/tektoncd/dashboard/pkg/utils"
k8sinformer "k8s.io/client-go/informers"
)

Expand All @@ -12,11 +13,12 @@ import (
func NewSecretController(sharedK8sInformerFactory k8sinformer.SharedInformerFactory) {
logging.Log.Debug("In NewSecretController")

utils.NewController(
controllerUtils.NewController(
"secret",
sharedK8sInformerFactory.Core().V1().Secrets().Informer(),
broadcaster.SecretCreated,
broadcaster.SecretUpdated,
broadcaster.SecretDeleted,
utils.SanitizeSecret,
)
}
1 change: 1 addition & 0 deletions pkg/controllers/kubernetes/serviceAccount.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ func NewServiceAccountController(sharedK8sInformerFactory k8sinformer.SharedInfo
broadcaster.ServiceAccountCreated,
broadcaster.ServiceAccountUpdated,
broadcaster.ServiceAccountDeleted,
nil,
)
}
1 change: 1 addition & 0 deletions pkg/controllers/tekton/clustertask.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ func NewClusterTaskController(sharedTektonInformerFactory tektoninformer.SharedI
broadcaster.ClusterTaskCreated,
broadcaster.ClusterTaskUpdated,
broadcaster.ClusterTaskDeleted,
nil,
)
}
1 change: 1 addition & 0 deletions pkg/controllers/tekton/pipeline.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ func NewPipelineController(sharedTektonInformerFactory tektoninformer.SharedInfo
broadcaster.PipelineCreated,
broadcaster.PipelineUpdated,
broadcaster.PipelineDeleted,
nil,
)
}
1 change: 1 addition & 0 deletions pkg/controllers/tekton/pipelineresource.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ func NewPipelineResourceController(sharedTektonInformerFactory tektonresourceinf
broadcaster.PipelineResourceCreated,
broadcaster.PipelineResourceUpdated,
broadcaster.PipelineResourceDeleted,
nil,
)
}
1 change: 1 addition & 0 deletions pkg/controllers/tekton/pipelinerun.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ func NewPipelineRunController(sharedTektonInformerFactory tektoninformer.SharedI
broadcaster.PipelineRunCreated,
broadcaster.PipelineRunUpdated,
broadcaster.PipelineRunDeleted,
nil,
)
}
1 change: 1 addition & 0 deletions pkg/controllers/tekton/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ func NewTaskController(sharedTektonInformerFactory tektoninformer.SharedInformer
broadcaster.TaskCreated,
broadcaster.TaskUpdated,
broadcaster.TaskDeleted,
nil,
)
}
1 change: 1 addition & 0 deletions pkg/controllers/tekton/taskrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ func NewTaskRunController(sharedTektonInformerFactory tektoninformer.SharedInfor
broadcaster.TaskRunCreated,
broadcaster.TaskRunUpdated,
broadcaster.TaskRunDeleted,
nil,
)
}
17 changes: 12 additions & 5 deletions pkg/controllers/utils/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,26 @@ import (
"github.com/tektoncd/dashboard/pkg/broadcaster"
"github.com/tektoncd/dashboard/pkg/endpoints"
"github.com/tektoncd/dashboard/pkg/logging"
"github.com/tektoncd/dashboard/pkg/utils"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/cache"
)

func NewController(kind string, informer cache.SharedIndexInformer, onCreated, onUpdated, onDeleted broadcaster.MessageType) {
func NewController(kind string, informer cache.SharedIndexInformer, onCreated, onUpdated, onDeleted broadcaster.MessageType, filter func(interface{}, bool) interface{}) {
logging.Log.Debug("In NewController")

if filter == nil {
filter = func(obj interface{}, skipDeletedCheck bool) interface{} {
return obj
}
}

informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
logging.Log.Debugf("Controller detected %s '%s' created", kind, obj.(metav1.Object).GetName())
data := broadcaster.SocketData{
MessageType: onCreated,
Payload: obj,
Payload: filter(obj, true),
}
endpoints.ResourcesChannel <- data
},
Expand All @@ -27,16 +34,16 @@ func NewController(kind string, informer cache.SharedIndexInformer, onCreated, o
logging.Log.Debugf("Controller detected %s '%s' updated", kind, oldSecret.GetName())
data := broadcaster.SocketData{
MessageType: onUpdated,
Payload: newObj,
Payload: filter(newObj, true),
}
endpoints.ResourcesChannel <- data
}
},
DeleteFunc: func(obj interface{}) {
logging.Log.Debugf("Controller detected %s '%s' deleted", kind, GetDeletedObjectMeta(obj).GetName())
logging.Log.Debugf("Controller detected %s '%s' deleted", kind, utils.GetDeletedObjectMeta(obj).GetName())
data := broadcaster.SocketData{
MessageType: onDeleted,
Payload: obj,
Payload: filter(obj, false),
}
endpoints.ResourcesChannel <- data
},
Expand Down
47 changes: 0 additions & 47 deletions pkg/controllers/utils/utils.go

This file was deleted.

95 changes: 72 additions & 23 deletions pkg/endpoints/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ import (
"net/http"
"net/url"
"os"
"regexp"
"strconv"
"strings"

restful "github.com/emicklei/go-restful"
"github.com/gorilla/csrf"
"github.com/tektoncd/dashboard/pkg/logging"
"github.com/tektoncd/dashboard/pkg/utils"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/rest"
)

// Properties : properties we want to be able to retrieve via REST
Expand All @@ -46,6 +49,8 @@ const (
tektonDashboardRouteName string = "tekton-dashboard"
)

var secretsURIPattern *regexp.Regexp = regexp.MustCompile("/secrets[?/]")

// ProxyRequest does as the name suggests: proxies requests and logs what's going on
func (r Resource) ProxyRequest(request *restful.Request, response *restful.Response) {
parsedURL, err := url.Parse(request.Request.URL.String())
Expand All @@ -59,31 +64,14 @@ func (r Resource) ProxyRequest(request *restful.Request, response *restful.Respo
forwardRequest.SetHeader("Content-Type", request.HeaderParameter("Content-Type"))
forwardResponse := forwardRequest.Do()

if secretsURIPattern.Match([]byte(uri)) {
handleSecretsResponse(response, forwardResponse)
return
}

responseBody, requestError := forwardResponse.Raw()
if requestError != nil {
errorInfo := string(responseBody)
errorInfo = strings.Replace(errorInfo, "\"", "", -1)
errorInfo = strings.Replace(errorInfo, "\\", "", -1)
errorInfo = strings.Replace(errorInfo, "\n", "", -1)
// Checks if an error code can be found in the response
if strings.LastIndex(errorInfo, "code:") != -1 {
errorCodeString := strings.LastIndex(errorInfo, "code:")
// Checks if the code is 3-digits long
if len(errorInfo[errorCodeString+5:errorCodeString+8]) == 3 {
errorCode := errorInfo[errorCodeString+5 : errorCodeString+8]
errorCodeFormatted, err := strconv.Atoi(errorCode)
// Checks if the code can be converted to an integer without error
if err != nil {
utils.RespondError(response, requestError, http.StatusInternalServerError)
return
}
utils.RespondError(response, errors.New(errorInfo), errorCodeFormatted)
return
}
utils.RespondError(response, requestError, http.StatusInternalServerError)
return
}
utils.RespondError(response, requestError, http.StatusInternalServerError)
handleRequestError(response, responseBody, requestError)
return
}
response.Header().Add("Content-Type", utils.GetContentType(responseBody))
Expand Down Expand Up @@ -205,3 +193,64 @@ func (r Resource) GetToken(request *restful.Request, response *restful.Response)
response.Header().Add("X-CSRF-Token", csrf.Token(request.Request))
response.Write([]byte("OK"))
}

func handleRequestError(response *restful.Response, responseBody []byte, requestError error) {
errorInfo := string(responseBody)
errorInfo = strings.Replace(errorInfo, "\"", "", -1)
errorInfo = strings.Replace(errorInfo, "\\", "", -1)
errorInfo = strings.Replace(errorInfo, "\n", "", -1)
// Checks if an error code can be found in the response
if strings.LastIndex(errorInfo, "code:") != -1 {
errorCodeString := strings.LastIndex(errorInfo, "code:")
// Checks if the code is 3-digits long
if len(errorInfo[errorCodeString+5:errorCodeString+8]) == 3 {
errorCode := errorInfo[errorCodeString+5 : errorCodeString+8]
errorCodeFormatted, err := strconv.Atoi(errorCode)
// Checks if the code can be converted to an integer without error
if err != nil {
utils.RespondError(response, requestError, http.StatusInternalServerError)
return
}
utils.RespondError(response, errors.New(errorInfo), errorCodeFormatted)
return
}
utils.RespondError(response, requestError, http.StatusInternalServerError)
return
}
utils.RespondError(response, requestError, http.StatusInternalServerError)
}

func handleSecretsResponse(response *restful.Response, forwardResponse rest.Result) {
responseBody, requestError := forwardResponse.Get()
if requestError != nil {
responseBodyRaw, requestError := forwardResponse.Raw()
handleRequestError(response, responseBodyRaw, requestError)
return
}

var responseObject interface{}

list, _ := responseBody.(*corev1.SecretList)
if list != nil {
logging.Log.Debug("Processing SecretList response")
secrets := make([]corev1.Secret, 0, len(list.Items))
for _, secret := range list.Items {
secrets = append(secrets, utils.SanitizeSecret(&secret, true).(corev1.Secret))
}
list.Items = secrets
responseObject = list
} else {
secret, _ := responseBody.(*corev1.Secret)
if secret != nil {
logging.Log.Debug("Processing Secret response")
responseObject = utils.SanitizeSecret(secret, true).(corev1.Secret)
} else {
responseObject = responseBody.(*metav1.Status)
}
}

var statusCode *int = new(int)
forwardResponse.StatusCode(statusCode)
response.Header().Add("Content-Type", restful.MIME_JSON)
response.WriteHeaderAndEntity(*statusCode, responseObject)
}
Loading

0 comments on commit 410c7ca

Please sign in to comment.