Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sidecar security context #12

Closed
wants to merge 12 commits into from
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Changelog

All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [0.1.1] - 2024-09-27

- Updated the security context of the sidecar container

```shell
Capabilities: &corev1.Capabilities{
Add: []corev1.Capability{"NET_ADMIN", "NET_BIND_SERVICE"},
Drop: []corev1.Capability{"ALL"},
},
RunAsUser: &rootUser, (deafault = true)
Privileged: &isPrivileged, (default = false)
```

## [0.1.0] - 2024-08-08

- Added initial code.

2 changes: 1 addition & 1 deletion ziti-agent/cmd/common/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/spf13/cobra"
)

var Version = "0.1.0"
var Version = "0.1.1"

func NewVersionCmd() *cobra.Command {
return &cobra.Command{
Expand Down
58 changes: 58 additions & 0 deletions ziti-agent/cmd/webhook/mux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package webhook

import (
"net/http"

"golang.org/x/time/rate"
)

// Rate limit - 1 token to be consumed per second, with a maximum burst size of 3.
var rateLimiter = rate.NewLimiter(rate.Limit(1), 3)

// CustomServeMux implements a custom ServeMux with a rate limiter and channel queue
type customMux struct {
*http.ServeMux
// queue chan *http.Request
// wg sync.WaitGroup
}

func NewCustomMux() *customMux {
return &customMux{
http.NewServeMux(),
// make(chan *http.Request, 10),
// sync.WaitGroup{},
}
}

func (m *customMux) Handle(pattern string, handler http.HandlerFunc) {
m.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
// Check rate limit
if rateLimiter.Allow() == false {
http.Error(w, http.StatusText(429), http.StatusTooManyRequests)
return
}

// m.queue <- r
// m.wg.Add(1)

// defer m.wg.Done()

// for {
// select {
// case req := <-m.queue:
// m.ServeMux.ServeHTTP(w, req)
// case <-context.Background().Done():
// return
// }
// }

// Serve next request
m.ServeMux.ServeHTTP(w, r)
})
}

// func (m *customMux) Shutdown(ctx context.Context) error {
// close(m.queue)
// m.wg.Wait()
// return nil
// }
29 changes: 17 additions & 12 deletions ziti-agent/cmd/webhook/pods.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import (
k "github.com/netfoundry/ziti-k8s-agent/ziti-agent/kubernetes"
ze "github.com/netfoundry/ziti-k8s-agent/ziti-agent/ziti-edge"

"github.com/google/uuid"
"github.com/openziti/edge-api/rest_management_api_client"
"github.com/openziti/sdk-golang/ziti"
admissionv1 "k8s.io/api/admission/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog/v2"
)

Expand Down Expand Up @@ -71,7 +71,7 @@ func zitiTunnel(ar admissionv1.AdmissionReview) *admissionv1.AdmissionResponse {
return failureResponse(reviewResponse, err)
}

identityCfg, sidecarIdentityName, err := createAndEnrollIdentity(pod.Labels["app"], roles, zec)
identityCfg, sidecarIdentityName, err := createAndEnrollIdentity(pod.Labels["app"], ar.Request.UID, roles, zec)
if identityCfg == nil {
return failureResponse(reviewResponse, err)
}
Expand Down Expand Up @@ -146,17 +146,26 @@ func zitiTunnel(ar admissionv1.AdmissionReview) *admissionv1.AdmissionResponse {
var patch []JsonPatchEntry
var rootUser int64 = 0
var isNotTrue bool = false
var isPrivileged = false
var sidecarSecurityContext *corev1.SecurityContext

sidecarSecurityContext = &corev1.SecurityContext{
Capabilities: &corev1.Capabilities{Add: []corev1.Capability{"NET_ADMIN"}},
Capabilities: &corev1.Capabilities{
Add: []corev1.Capability{"NET_ADMIN", "NET_BIND_SERVICE"},
Drop: []corev1.Capability{"ALL"},
},
RunAsUser: &rootUser,
Privileged: &isPrivileged,
}

if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.RunAsUser != nil {
// run sidecar as root
sidecarSecurityContext = &corev1.SecurityContext{
Capabilities: &corev1.Capabilities{Add: []corev1.Capability{"NET_ADMIN"}},
RunAsUser: &rootUser,
Capabilities: &corev1.Capabilities{
Add: []corev1.Capability{"NET_ADMIN", "NET_BIND_SERVICE"},
Drop: []corev1.Capability{"ALL"},
},
RunAsUser: &rootUser,
Privileged: &isPrivileged,
}
}

Expand Down Expand Up @@ -328,13 +337,9 @@ func hasContainer(containers []corev1.Container, containerName string) (string,
return "", false
}

func createSidecarIdentityName(appName string) string {
id, _ := uuid.NewV7()
return fmt.Sprintf("%s-%s%s", trimString(appName), sidecarPrefix, id)
}
func createAndEnrollIdentity(name string, uid types.UID, roles []string, zec *rest_management_api_client.ZitiEdgeManagement) (*ziti.Config, string, error) {

func createAndEnrollIdentity(name string, roles []string, zec *rest_management_api_client.ZitiEdgeManagement) (*ziti.Config, string, error) {
identityName := createSidecarIdentityName(name)
identityName := fmt.Sprintf("%s-%s%s", trimString(name), sidecarPrefix, uid)

identityDetails, err := ze.CreateIdentity(identityName, roles, "Device", zec)
if err != nil {
Expand Down
7 changes: 5 additions & 2 deletions ziti-agent/cmd/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func serve(w http.ResponseWriter, r *http.Request, admit admitHandler) {
responseAdmissionReview.Response.UID = requestedAdmissionReview.Request.UID
responseObj = responseAdmissionReview

klog.Infof(fmt.Sprintf("Admission Response v1: %s", responseObj))
klog.Infof(fmt.Sprintf("Admission Response UID: %s", responseAdmissionReview.Response.UID))

case admissionv1.SchemeGroupVersion.WithKind("AdmissionReview"):
requestedAdmissionReview, ok := obj.(*admissionv1.AdmissionReview)
Expand Down Expand Up @@ -164,11 +164,14 @@ func webhook(cmd *cobra.Command, args []string) {
// load env vars to override the command line vars if any
lookupEnvVars()

// setup custom mux
mux := NewCustomMux()
mux.HandleFunc("/ziti-tunnel", serveZitiTunnelSC)
klog.Infof("AC WH Server is listening on port %d", port)
http.HandleFunc("/ziti-tunnel", serveZitiTunnelSC)
server := &http.Server{
Addr: fmt.Sprintf(":%d", port),
TLSConfig: configTLS(cert, key),
Handler: mux,
}
err := server.ListenAndServeTLS("", "")
if err != nil {
Expand Down
Loading