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

Allow running as non root user #27

Closed
constanca-m opened this issue Oct 2, 2024 · 0 comments
Closed

Allow running as non root user #27

constanca-m opened this issue Oct 2, 2024 · 0 comments

Comments

@constanca-m
Copy link
Contributor

constanca-m commented Oct 2, 2024

The dockerfile does not specifiy a user. From the documentation:

When the user doesn't have a primary group then the image (or the next instructions) will be run with the root group.

We can also see from this blogpost from Docker that it is a best practice to run as non root user.

I have tried to do it by adding

spec:
  securityContext:
    runAsNonRoot: true

to my gubernator pod.

You can see the complete manifest here.
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: gubernator
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: get-endpoints
rules:
  - apiGroups:
      - ""
    resources:
      - endpoints
    verbs:
      - list
      - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: get-endpoints
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: get-endpoints
subjects:
  - kind: ServiceAccount
    name: gubernator
---
apiVersion: v1
kind: Pod
metadata:
  name: gubernator
  labels:
    app: gubernator
spec:
  securityContext:
    runAsNonRoot: true
  serviceAccountName: gubernator
  containers:
    - image: ghcr.io/gubernator-io/gubernator:latest
      imagePullPolicy: IfNotPresent
      ports:
        - name: grpc-port
          containerPort: 81
        - name: http-port
          containerPort: 80
      name: gubernator
      env:
      - name: GUBER_K8S_NAMESPACE
        valueFrom:
          fieldRef:
            fieldPath: metadata.namespace
      - name: GUBER_K8S_POD_IP
        valueFrom:
          fieldRef:
            fieldPath: status.podIP
      # Must set the GRPC and HTTP addresses, as gubernator
      # defaults to listening on localhost only
      - name: GUBER_GRPC_ADDRESS
        value: 0.0.0.0:81
      - name: GUBER_HTTP_ADDRESS
        value: 0.0.0.0:80
      # Use the k8s API for peer discovery
      - name: GUBER_PEER_DISCOVERY_TYPE
        value: "k8s"
      # This should match the port number GRPC is listening on
      # as defined by `containerPort`
      - name: GUBER_K8S_POD_PORT
        value: "81"
      # The selector used when listing endpoints. This selector
      # should only select gubernator peers.
      - name: GUBER_K8S_ENDPOINTS_SELECTOR
        value: "app=gubernator"
      # Gubernator can watch 'endpoints' for changes to the peers
      # or it can watch 'pods' (Defaults to 'endpoints')
      # - name: GUBER_K8S_WATCH_MECHANISM
      #  value: "endpoints"
      # Enable debug for diagnosing issues
      - name: GUBER_DEBUG
        value: "true"
      # Defines the max age of a client connection
      # Default is infinity
      # - name: GUBER_GRPC_MAX_CONN_AGE_SEC
      #  value: "30"

  restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  name: gubernator
  labels:
    app: gubernator
spec:
  type: LoadBalancer
  ports:
  - targetPort: 80
    port: 80
  selector:
    app: gubernator

This does not work. It fails with:

Error: container has runAsNonRoot and image will run as root (pod: "gubernator-794fb7b76f-6vntp_default(8e4c444e-68ec-4800-9dd5-668a593a7b65)", container: gubernator)

To run as non root user, it would need to change:

  1. Create a non root user in the Dockerfile. This would be ideally done in the build phase, since scratch image does not have the commands to do this. Then switch to the new user in the next phase.
  2. I think the defaults would have to change since they use 0.0.0.0:80 and 0.0.0.0:81, which seems to be by default ports for root users. I could not find documentation on this, but I have tried running it like this and it did not work.
Here is an example script to test these changes in a local K8s cluster.
# delete local cluster if exists
kind delete cluster

# expose load balancer
cloud-provider-kind > cloud-provider-kind.log 2>&1 &
kind create cluster

docker build -t custom-image .
kind load docker-image custom-image:latest
# ensure gubernator pod is using image: custom-image:latest
kubectl apply -f k8s-deployment.yaml

# wait until gubernator is ready
kubectl wait --for=jsonpath='{.status.loadBalancer.ingress}' service/gubernator
kubectl wait --for=condition=Ready pod/gubernator --timeout=5m

# check the pod and service
kubectl get all

# make a request
IP=$(kubectl get service/gubernator -o=jsonpath='{.status.loadBalancer.ingress[0].ip}')
ENDPOINT="http://$IP:80/v1/GetRateLimits"
echo "ENDPOINT IS $ENDPOINT"
curl $ENDPOINT \
  --header 'Content-Type: application/json' \
  --data '{
    "requests": [
        {
            "name": "requests_per_sec",
            "uniqueKey": "account:12345",
            "hits": "1",
            "limit": "10",
            "duration": "1000"
        }
    ]
}'

PR: #28

@constanca-m constanca-m changed the title Runnin as non root user Allow running as non root user Oct 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant