<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mateus Caruccio</title>
    <description>The latest articles on DEV Community by Mateus Caruccio (@caruccio).</description>
    <link>https://dev.to/caruccio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F25654%2Fc3794de3-cd8c-4924-a3ca-45fe00b6e65b.jpeg</url>
      <title>DEV Community: Mateus Caruccio</title>
      <link>https://dev.to/caruccio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/caruccio"/>
    <language>en</language>
    <item>
      <title>Kubernetes hack</title>
      <dc:creator>Mateus Caruccio</dc:creator>
      <pubDate>Sun, 23 Jun 2024 17:08:52 +0000</pubDate>
      <link>https://dev.to/caruccio/kubernetes-hack-1d0p</link>
      <guid>https://dev.to/caruccio/kubernetes-hack-1d0p</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;NOTE: this is an updated copy of my &lt;a href="https://medium.com/@mateus.caruccio/kubernetes-hack-lost-ssh-access-to-node-5dd36d35c74c" rel="noopener noreferrer"&gt;post in medium&lt;/a&gt;, where I'm not writing anymore.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Have you lost ssh access to one of your Kubernetes nodes? Why do you even need ssh access to nodes in the first place? Well, maybe something is stuck, or you need to see a config with your own eyes… I don’t know and I don’t care, they are your servers, not mine…&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I’m assuming you have admin level into kubernetes API.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Talk is cheap, show me the code®:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ NODE_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;master-0
&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl create &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
apiVersion: v1
kind: Pod
metadata:
  name: root-shell-&lt;/span&gt;&lt;span class="nv"&gt;$NODE_NAME&lt;/span&gt;&lt;span class="sh"&gt;
  namespace: kube-system
spec:
  nodeName: &lt;/span&gt;&lt;span class="nv"&gt;$NODE_NAME&lt;/span&gt;&lt;span class="sh"&gt;
  containers:
  - command:
    - /bin/cat
    image: alpine:3
    name: root-shell
    securityContext:
      #privileged: true
      allowPrivilegeEscalation: true
      readOnlyRootFilesystem: true
      runAsGroup: 0
      runAsUser: 0
      capabilities:
        drop:
        - ALL
      seLinuxOptions:
        level: s0
        user: system_u
    tty: true
    stdin: true
    volumeMounts:
    - mountPath: /host
      name: hostroot
  hostNetwork: true
  hostPID: true
  hostIPC: true
  tolerations:
  - effect: NoSchedule
    operator: Exists
  - effect: NoExecute
    operator: Exists
  volumes:
  - hostPath:
      path: /
    name: hostroot
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pod will create a privileged POD into the node master-0 (change it to your node name) running /bin/cat forever. Now you simply exec into it and change the host’s root to pod’s root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; root-shell-&lt;span class="nv"&gt;$NODE_NAME&lt;/span&gt; &lt;span class="nb"&gt;chroot&lt;/span&gt; /host /bin/bash
&lt;span class="o"&gt;[&lt;/span&gt;root@master-0 /]# &lt;span class="nb"&gt;id
&lt;/span&gt;&lt;span class="nv"&gt;uid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0&lt;span class="o"&gt;(&lt;/span&gt;root&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;gid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0&lt;span class="o"&gt;(&lt;/span&gt;root&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;groups&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0&lt;span class="o"&gt;(&lt;/span&gt;root&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Profit!&lt;/p&gt;

&lt;p&gt;PS: Here is a DaemonSet for the lazy like me.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl create serviceaccount &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system root-shell
&lt;span class="c"&gt;### For OKD/Openshift clusters only:&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;oc adm add-scc-to-user privileged &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system &lt;span class="nt"&gt;-z&lt;/span&gt; root-shell
&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl create &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: root-shell
  namespace: kube-system
spec:
  revisionHistoryLimit: 0
  selector:
    matchLabels:
      app: root-shell
  template:
    metadata:
      labels:
        app: root-shell
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - command:
        - /bin/cat
        image: alpine:3
        name: root-shell
        tty: true
        stdin: true
        volumeMounts:
        - mountPath: /host
          name: hostroot
        #securityContext:
        #  privileged: true
        allowPrivilegeEscalation: true
        readOnlyRootFilesystem: true
        runAsGroup: 0
        runAsUser: 0
        capabilities:
          drop:
          - ALL
        seLinuxOptions:
          level: s0
          user: system_u
      hostNetwork: true
      hostPID: true
      hostIPC: true
      serviceAccountName: root-shell
      hostNetwork: true
      tolerations:
      - effect: NoSchedule
        operator: Exists
      - effect: NoExecute
        operator: Exists
      volumes:
      - hostPath:
          path: /
        name: hostroot
  updateStrategy:
    rollingUpdate:
      maxUnavailable: 100%
    type: RollingUpdate
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  AWS Bottlerocket
&lt;/h2&gt;

&lt;p&gt;Since now bottlerocket is a really nice OS alternative in EKS clusters, lets use control/admin containers to gain root-level access to the host.&lt;/p&gt;

&lt;p&gt;As you known, Bottlerocket is a Read-only, container oriented operating system. This gives us a lot of benefits, but you can't simply &lt;code&gt;kubect exec + chroot&lt;/code&gt; into it as we did in the stone age. Turns out there is two containers in the system: control and admin. We whant admin, since control is for adminstrative tasks (like upgrades and reboots).&lt;/p&gt;

&lt;p&gt;First, we need a plain container to have access to host's &lt;code&gt;apiclient&lt;/code&gt; binary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl create &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system &lt;span class="nt"&gt;-f&lt;/span&gt; - &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: apiclient
  namespace: kube-system
spec:
  revisionHistoryLimit: 0
  selector:
    matchLabels:
      app: apiclient
  template:
    metadata:
      labels:
        app: apiclient
    spec:
      containers:
      - command:
        - sleep
        - infinity
        image: fedora
        imagePullPolicy: Always
        name: regain-access
        securityContext:
          seLinuxOptions:
            level: s0
            role: system_r
            type: control_t
            user: system_u
        volumeMounts:
        - mountPath: /usr/bin/apiclient
          name: apiclient
          readOnly: true
        - mountPath: /run/api.sock
          name: apiserver-socket
      restartPolicy: Always
      terminationGracePeriodSeconds: 0
      volumes:
      - hostPath:
          path: /usr/bin/apiclient
          type: File
        name: apiclient
      - hostPath:
          path: /run/api.sock
          type: Socket
        name: apiserver-socket
  updateStrategy:
    rollingUpdate:
      maxUnavailable: 100%
    type: RollingUpdate
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that in place, let's use &lt;code&gt;apiclient exec&lt;/code&gt; subcommand to activate and enter admin container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system apiclient-xtwxh &lt;span class="nt"&gt;--&lt;/span&gt; apiclient &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; control enter-admin-container
Confirming admin container is enabled...
Waiting &lt;span class="k"&gt;for &lt;/span&gt;admin container to start...
Entering admin container
          Welcome to Bottlerocket&lt;span class="s1"&gt;'s admin container!
    ╱╲
   ╱┄┄╲   This container provides access to the Bottlerocket host
   │▗▖│   filesystems (see /.bottlerocket/rootfs) and contains common
  ╱│  │╲  tools for inspection and troubleshooting.  It is based on
  │╰╮╭╯│  Amazon Linux 2, and most things are in the same places you
    ╹╹    would find them on an AL2 host.

To permit more intrusive troubleshooting, including actions that mutate the
running state of the Bottlerocket host, we provide a tool called "sheltie"
(`sudo sheltie`).  When run, this tool drops you into a root shell in the
Bottlerocket host'&lt;/span&gt;s root filesystem.
&lt;span class="o"&gt;[&lt;/span&gt;root@admin]#
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the time of this writing, all you have to do now is execute &lt;code&gt;sudo sheltie&lt;/code&gt; and voilà!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;root@admin]# &lt;span class="nb"&gt;sudo &lt;/span&gt;sheltie
bash-5.1# ps 1
    PID TTY      STAT   TIME COMMAND
      1 ?        Ss    14:25 /sbin/init systemd.log_target&lt;span class="o"&gt;=&lt;/span&gt;journal-or-kmsg systemd.log_color&lt;span class="o"&gt;=&lt;/span&gt;0 systemd.show_status&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;bash-5.1# 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>kubernetes</category>
      <category>shell</category>
    </item>
  </channel>
</rss>
