Friday, August 16, 2024

Useful Google Cloud Logs (Stackdriver) Query Filters

GKE create cluster
protoPayload.methodName="google.container.v1.ClusterManager.CreateCluster"
All GKE cluster logs
resource.type="gke_cluster"
Access transparency logs
logName="projects/[PROJECT_ID]/logs/cloudaudit.googleapis.com%2Faccess_transparency"
OR
jsonPayload.@type="type.googleapis.com/google.cloud.audit.TransparencyLog"

Friday, February 9, 2024

Listing TLS cipher suites

Nmap will list the ciphersuites of a server, and do some warning about old ones:
nmap --script ssl-enum-ciphers -p 443 www.example.com

Thursday, January 5, 2023

Gatekeeper/policycontroller kubectl cheat sheet

Gatekeeper/policycontroller cheat sheet.

List all the constraint templates
kubectl get constrainttemplates -l="configmanagement.gke.io/configmanagement=config-management"
Get the status of a particular constraint, including logged violations:
kubectl get k8sallowedrepos.constraints.gatekeeper.sh repo-is-gcr
Get the policy controller logs:
kubectl logs -n gatekeeper-system -l gatekeeper.sh/system=yes

Wednesday, January 4, 2023

Replacements for docker

 With docker changing its license and the general problem of running a super privileged daemon, I've been looking for alternatives. Here's what I've found to work.

Gcrane for interacting with registries:


go install github.com/google/go-containerregistry/cmd/gcrane@latest
export PATH="${HOME}/go/bin:$PATH"

gcrane pull ubuntu ubuntu.tar
gcrane push ubuntu.tar gcr.io/my-project/ubuntu
gcrane cp ubuntu gcr.io/my-project/ubuntu

Podman for building and pushing

sudo apt-get install podman
If you get this warning:
Reading allowed ID mappings: reading subuid mappings for user "${USER}" and subgid mappings for group "${USER}": no subuid ranges found for user "${USER}" in /etc/subuid
You need to add some UIDs:
sudo usermod --add-subuids ${start_uid:=100000}-$(( ${start_uid:=100000} + "65535" )) $(whoami)
sudo usermod --add-subgids ${start_gid:=100000}-$(( ${start_gid:=100000} + "65535" )) $(whoami)
Then you can use it:
podman build -t ${IMG}:${TAG} .

# Auth to an artifact registry repo
gcloud auth print-access-token | podman login -u oauth2accesstoken --password-stdin ${REGION}-docker.pkg.dev
podman push ${REGION}-docker.pkg.dev/${PROJECT}/${REPO}/${IMG}:${TAG}

# Run a container
podman run --rm -it alpine:latest /bin/sh

Monday, September 26, 2022

Unpatchable vulnerabilities detected by scanners

There's quite a lot of vulnerabilities in the NVD that aren't really vulnerabilities but may show up in vulnerability scanners depending on the behavior of the scanner. Here's some examples of open vulnerabilities (pulled from a debian container that's up-to-date at the time of writing) that just aren't vulnerabilities at all:
As raesene@ points out whether these show up in your container vulnerability scanner depends entirely on the scanner. Empirical testing shows that nessus filters out quite a lot of unactionable vulnerability scan results, whereas free scanners like Trivy, or even other paid scanners, don't. They take the approach of "show everything, but you can filter out the actionable vulns that have patches".

The second approach is the easiest and least controversial for the scanner implementor because they don't have to make any security decisions about what to show or not show. It effectively delegates the problem of filtering out the noise to the user. The first problem is that the default view is very noisy and it's not immediately obvious how to make it better, especially for practitioners coming from scanners that filter the noise up-front. It takes effort to get to a sensible view.

The second problem is that if you just filter vulns by which ones have patches, to eliminate the this-isn't-a-vuln entries from 2005, you may miss something important that isn't patched yet but that you should be mitigating with a workaround or settings change.

I don't think we're doing users any favors by continuing to put 18-year-old "vulnerabilities" that were never vulnerabilities in their scan results. It's harder to do, but I think a line should be drawn by the scanner as nessus does.

Other ancient unactionable vulnerabilities you'll see, in tools that don't filter up-front, are technically vulnerabilities but low enough severity that no-one has gotten around to fixing them for years. Some are incompatible with current software so there's no obvious fix without something like a new kernel syscall.
Should these be filtered out? From the user's, i.e. the scan consumer's, point of view they are basically useless. It's not like the average practitioner has the skills or time to go fix these, and even if they did the projects may just reject the fixes.

Showing them in tools, "i.e. many eyes", isn't exerting much pressure on getting them fixed because they are all multiple years old or completely abandoned. From a scanner implementor point of view the decision on whether to show them is more difficult, because unlike the first list these are real vulns, just not important ones that are going to be fixed inside of any kind of compliance SLO.

So should a scanner hide a "real" vuln? Or show the user an unpatchable vuln in their dashboard that may, depending on the user's specific compliance requirements, trigger a need to write monthly deviation requests forever? Tough choice.

Thursday, June 9, 2022

GNOME desktop: disabling all the annoying stuff

 Sadly GNOME seems to be missing (or has removed) options to disable all of the annoying stuff it's doing.

To disable the stupid workspace switching animation you have to install an entire extension. I installed this one directly from github, the code is tiny, you can read it.

To turn off the hotcorner that I continually accidentally hit there is apparently no longer a UI option, but running:

gsettings set org.gnome.desktop.interface enable-hot-corners false

worked.

Annoyingly the UI control you do have is not anywhere intuitive like with GNOME in the name. It's in "tweaks" and "extensions".  Tweaks is where you can adjust font size, Extensions is where the workspace switching toggle shows up and also where you can disable the applications menu.

Thursday, June 3, 2021

Quick summary of the cybersecurity executive order

Exec order is here, fact sheet summary. Good analysis from lawfare blog here.
  • Share info on incidents (anything that impacts CIA according to 44 U.S.C. 3552(b)(2), which could be read incredibly broadly) by amending gov contractual language.
  • Zero trust all the things. Make a plan to adopt zero trust as defined by NIST. It's basically defense in depth plus least privilege and seems about as likely to make progress as a result of this order as those general ideas have made in the last 15 years.
  • Use FedRAMP to set a cloud security strategy and adopt new cloud security principles. FedRAMP will develop "cloud-security technical reference architecture documentation that illustrates recommended approaches to cloud migration and data protection for agency data collection and reporting."
  • CISA to develop "a cloud services governance framework" which sounds like it's to help with gov IR: "identify a range of services and protections available to agencies based on incident severity".
  • Gov agencies must identify and report sensitive unclass data. I interpret this as the beginning of a process to adjust thinking from "unclass data doesn't matter" to a more sensible data classification that isn't solely focused on impact to national security.
  • MFA and "encryption at rest and in transit" within 180 days for all gov agencies. Reports every 60 days after.
  • Train gov agencies on FedRAMP and automate fedramp comms/forms with CSPs. Map compliance requirements onto FedRAMP authorization requirements and rely on the compliance certs instead of re-doing work for FedRAMP.
  • Publish secure software supply chain guidelines for "critical software" within 180 days, NIST to publish 90 days after that. Preview of requirements around providing purchaser a software bill of materials, proof of provenance, vuln disclosure etc. Format of BOM to be decided and go into contract language within a year. This whole section is very optimistic.
  • Consider consumer labelling for IoT re secure supply chain. This isn't my field but if I was buying one of these devices I would love to know what the security patch frequency and EOL is.
  • Build a cyber safety review board that looks at big incidents modeled after the NTSB. This is great.
  • CISA to write an incident response playbook for all gov agencies. This might be helpful for agencies that have no such playbooks, and may be a hindrance for those that already have good agency-specific ones. A bad, and likely, outcome would be to force sophisticated response private sector companies to do worse security response because they need to follow the letter of the official government playbook.
  • EDR initiative: "CISA, to engage in cyber hunt, detection, and response activities". They get access to all data they need to do it, without any pre-authorization. This seems big. The lawfare blog points out that "Congress actually granted CISA expanded (and clarified) centralized threat-hunting authority in Section 1705 of the fiscal 2021 National Defense Authorization Act". Will we see a gov EDR product that has to be able to run on all gov-owned infra, including cloud?
  • Gov agencies need logs from CSPs and to be able to provide those logs to DHS for analysis. Logs need to be signed at export time to prove authenticity as they pass through multiple hands.
  • Classified systems should do the same or better as this exec order, without upsetting the existing rules/authorities.

Wednesday, May 12, 2021

Debug logs for nest wifi and google wifi

 There are no logs available in the app, but there's quite a lot available from the diagnostic report API. It's in protobuf format, so someone wrote a handy little parser.


go get github.com/benmanns/onhub/cmd/onhubdump
~/go/bin/onhubdump http://192.168.86.1/api/v1/diagnostic-report > logs.json

$ jq 'keys' logs.json 
[
  "commandOutputs",
  "fileLengths",
  "files",
  "networkConfig",
  "stormVersion",
  "unixTime",
  "unknown1",
  "unknownPairs",
  "version",
  "wanInfo",
  "whirlwindVersion"
]

$ jq -r '.files[].path' logs.json
/etc/lsb-release
/etc/resolv.conf
/proc/net/arp
/proc/slabinfo
/proc/meminfo
/sys/firmware/log
/var/log/debug-log/debug-log
/var/log/boot.log
/var/log/net.log
/var/log/update_engine/update_engine.20200102-000001
/var/log/update_engine/update_engine.20190102-000001
/var/lib/ap/monitor/wan_idle_usage
/var/lib/ap/monitor/child_idle_usage
/var/lib/ap/health-monitor/wan_connectivity_history
/var/log/ap_fresh_dns_messages
/var/log/ap_https_server_messages
/var/log/critical_events.log
/var/log/messages

# Get /var/log/messages content:

$ jq -r '.files[17].content' logs.json | less

Friday, August 21, 2020

DNS CNAME at the root of a domain

TIL about DNS CNAME "flattening" which is a cloudflare feature that allows you to put a CNAME at the domain root: something that is actually not allowed by the DNS RFC spec.

Why does that matter? I was helping a nonprofit who is using a website hosting company, but the nonprofit has its own domain name. The hosting company tells them to "create a CNAME pointing at blahblah.somehosting.com" which works great, I created "www.example.com" as a CNAME pointing to the hosting address.

But what about the "naked" domain? i.e. if I type example.com like a normal person instead of www.example.com it doesn't resolve, and I don't have anywhere to point it. The cloudflare solution as above is to allow you to do something non-RFC compliant and also put a CNAME record at the root.

Google domains takes a different approach, to solve the problem you can create a subdomain forward for "@" and point it at your www.example.com target. With "forward path" enabled on the entry the URLs will also be preserved through the redirect.

Under the hood Google creates A records for the root domain, so a request for the root domain will resolve to a Google service that then resolves your www.example.com CNAME, establishes a HTTP session with the requester and issues the requesting browser a 301/302 redirect.

Monday, May 25, 2020

Measuring internet bandwidth in a cron script speedtest.net

This is a simple way to keep tabs on bandwidth provided by your ISP. It's also useful as a historical record to prove exactly when service got worse.

The speedtest-cli is a python CLI for speedtest.net that has been dockerized by some kind folks.

To get a self-appending CSV just run:
/usr/bin/docker run --rm robertcsapo/speedtest --csv >> speedtest.csv
Assuming you run docker passwordless (actually a bad idea for security) you can then add this to your crontab. You may want to consider running it outside of when you need your network bandwidth the most:
0 1 * * * /usr/bin/docker run --rm robertcsapo/speedtest --csv >> /home/myuser/speedtest.csv
To do this with better security don't run docker passwordless, but allow sudo to run this specific command, where the userid 12345 is your userid that you can get by running 'id'. This will allow you to run this command as a non-root user:
myuser ALL=(ALL) NOPASSWD: /usr/bin/docker run -u 12345 --rm robertcsapo/speedtest --csv
And then in your cron put:
0 1 * * * sudo /usr/bin/docker run -u 12345 --rm robertcsapo/speedtest --csv >> /home/me/speedtest.csv

Thursday, January 2, 2020

Gatekeeper, OPA, rego: notes from testing and debugging policies

Installing gatekeeper is easy:
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml
We can see this creates configs and constrainttemplates CRDs:
$ kubectl api-resources | grep gatekeeper.sh
configs                                        config.gatekeeper.sh           true         Config
constrainttemplates                            templates.gatekeeper.sh        false        ConstraintTemplate
The constraints based off the constraintemplates will themselves will be their own CRDs. In the gatekeeper-system namespace we have the controller manager and webhook that will serve the validating webhook requests from the API server:
$ kubectl get all -n gatekeeper-system
NAME                                                 READY   STATUS    RESTARTS   AGE
pod/gatekeeper-controller-manager-77ff8cc995-sh8xq   1/1     Running   1          6d21h

NAME                                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/gatekeeper-webhook-service   ClusterIP   10.0.5.112           443/TCP   6d21h

NAME                                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/gatekeeper-controller-manager   1/1     1            1           6d21h

NAME                                                       DESIRED   CURRENT   READY   AGE
replicaset.apps/gatekeeper-controller-manager-77ff8cc995   1         1         1       6d21h
The next step is creating constraint templates, here's one that denies all Ingress:
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8snoexternalservices
spec:
  crd:
    spec:
      names:
        kind: K8sNoExternalServices
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8snoexternalservices

        violation[{"msg": msg}] {
          input.review.kind.kind == "Ingress"
          re_match("^(extensions|networking.k8s.io)$", input.review.kind.group)
          msg := sprintf("No external service exposure is allowed via ingress: %v", [input.review.object.metadata.name])
        }
But how did we know that it was input.review.kind.kind? That's pretty unintuitive. Turns out it's because that's the structure of the object passed to the authenticating webhook. We can see this by creating a constraint template that just blocks everything and logs the full object:
$ cat template.yaml
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sdebugtemplate
spec:
  crd:
    spec:
      names:
        kind: K8sDebugTemplate
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package debugging

        violation[{"msg": msg}] {
          msg := sprintf("Review object: %v", [input.review])
        }
$ kubectl apply -f template.yaml
And then apply that to ingress objects:
$ cat constraint.yaml 
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDebugTemplate 
metadata:
  name: debuggingdeny
spec:
  match:
    kinds:
      - apiGroups: ["extensions", "networking.k8s.io"]
        kinds: ["Ingress"]
$ kubectl apply -f constraint.yaml
$ kubectl api-resources --api-group=constraints.gatekeeper.sh
NAME                    SHORTNAMES   APIGROUP                    NAMESPACED   KIND
k8sdebugtemplate                     constraints.gatekeeper.sh   false        K8sDebugTemplate
Then when we create any ingress we get a full object logged:
$ cat basic-ingress.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: basic-ingress
  namespace: frontend
spec:
  backend:
    serviceName: web
    servicePort: 8080
If we patch an existing object we get to see old object filled out too:
$ kubectl patch -f basic-ingress.yaml -p '{"spec":{"backend":{"servicePort":8081}}}' 2>&1 | sed s'/): admission webhook.*//' | sed s'/.* Review object: //' | jq

{
  "operation": "UPDATE",
  "userInfo": {
    "username": "me@example.com",
    "groups": [
      "system:authenticated"
    ],
    "extra": {
      "user-assertion.cloud.google.com": [
        "XX=="
      ]
    }
  },
  "object": {
    "kind": "Ingress",
    "apiVersion": "extensions/v1beta1",
    "metadata": {
      "annotations": {
        "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"extensions/v1beta1\",\"kind\":\"Ingress\",\"metadata\":{\"annotations\":{},\"name\":\"basic-ingress\",\"namespace\":\"frontend\"},\"spec\":{\"backend\":{\"serviceName\":\"web\",\"servicePort\":8080}}}\n"
      },
      "finalizers": [
        "finalizers.gatekeeper.sh/sync"
      ],
      "name": "basic-ingress",
      "namespace": "frontend",
      "uid": "403d4a8f-2db0-11ea-828b-42010a80004c",
      "resourceVersion": "2135434",
      "generation": 2,
      "creationTimestamp": "2020-01-02T22:36:00Z"
    },
    "spec": {
      "backend": {
        "serviceName": "web",
        "servicePort": 8081
      }
    },
    "status": {
      "loadBalancer": {
        "ingress": [
          {
            "ip": "1.2.3.4"
          }
        ]
      }
    }
  },
  "oldObject": {
    "kind": "Ingress",
    "apiVersion": "extensions/v1beta1",
    "metadata": {
      "name": "basic-ingress",
      "namespace": "frontend",
      "uid": "403d4a8f-2db0-11ea-828b-42010a80004c",
      "resourceVersion": "2135434",
      "generation": 1,
      "creationTimestamp": "2020-01-02T22:36:00Z",
      "annotations": {
        "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"extensions/v1beta1\",\"kind\":\"Ingress\",\"metadata\":{\"annotations\":{},\"name\":\"basic-ingress\",\"namespace\":\"frontend\"},\"spec\":{\"backend\":{\"serviceName\":\"web\",\"servicePort\":8080}}}\n"
      },
      "finalizers": [
        "finalizers.gatekeeper.sh/sync"
      ]
    },
    "spec": {
      "backend": {
        "serviceName": "web",
        "servicePort": 8080
      }
    },
    "status": {
      "loadBalancer": {
        "ingress": [
          {
            "ip": "1.2.3.4"
          }
        ]
      }
    }
  },
  "uid": "6410973b-2db1-11ea-828b-42010a80004c",
  "kind": {
    "group": "extensions",
    "version": "v1beta1",
    "kind": "Ingress"
  },
  "resource": {
    "group": "extensions",
    "version": "v1beta1",
    "resource": "ingresses"
  },
  "options": null,
  "_unstable": {
    "namespace": {
      "kind": "Namespace",
      "apiVersion": "v1",
      "metadata": {
        "creationTimestamp": "2019-12-26T23:29:47Z",
        "annotations": {
          "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"name\":\"frontend\"}}\n"
        },
        "name": "frontend",
        "selfLink": "/api/v1/namespaces/frontend",
        "uid": "9a96616e-2837-11ea-8e60-42010a80017b",
        "resourceVersion": "33039"
      },
      "spec": {
        "finalizers": [
          "kubernetes"
        ]
      },
      "status": {
        "phase": "Active"
      }
    }
  },
  "name": "basic-ingress",
  "namespace": "frontend",
  "dryRun": false
}
We can clean up the debugging rule by deleting the constraint:
kubectl delete k8sdebugtemplate.constraints.gatekeeper.sh debuggingdeny 
In terms of policy writing you can test individual policies like this:
$ docker run -v /Users/gcastle/git/gatekeeper/library/general/uniqueingresshost:/tests openpolicyagent/opa test /tests/src.rego /tests/src_test.rego
PASS: 12/12
The current testing relies on rego assertions as tests, which is a bit of a PITA when you need to create a lot of test permutations on objects because you need to re-create the admission object above to some extent. It's also not super obvious what passing and failing are, it could do with a higher-level test framework:
  • "count(results) == 0" means pass this test if there were no violations
  • "count(results) == 1" means pass this test if there was exactly one violation
Bundling up templates is easy because gatekeeper is using kustomize. To create all the templates you could just do:
kustomize build templates | kubectl apply -f -

Monday, December 30, 2019

Vim regex examples

# Put a quote in front of the first alphabetic character on each line
s!\([a-z]\)!"\1!c

Sunday, March 24, 2019

Finding DNS servers provided by DHCP using network manager on Linux

Suppose you want to figure out which DNS server you're using and it is provided via DHCP. This can be surprisingly difficult. Suppose there's:
  1. Nothing in /etc/resolv.conf
  2. `dig google.com` shows your machine uses a local DNS server (local dnsmasq)
  3. /var/lib/dhcp/dhclient.leases looks...wrong
I resorted to:
sudo tcpdump -i eth0 -s0 -n 'udp port 53'
Which is guaranteed to show you what's going on. It turns out network manager stashes leases under its own directory. If you use
ps aux | grep dhclient
you can see network manager running dhclient (perhaps multiple instances per interface) and the -lf (lease file) parameter will point you at something like
/var/lib/NetworkManager/dhclient-[guid].lease
Mystery solved!

Sunday, August 26, 2018

Scrub GPS location from JPEG EXIF data

I tried two linux tools, exiv2 and exiftool. exiftool seems to be better.

exiv2

View full exif data with this (the default view only gives you a summary):
exiv2 -pa myimg.jpg 
Delete all exif data with this:
exiv2 rm myimg.jpg 
There doesn't appear to be a way to just delete the GPS info with exiv2.

exiftool

Install:
sudo apt-get install libimage-exiftool-perl
View exif data:
exiftool myimg.jpg
Delete just GPS data with this:
exiftool -gps:all= myimg.jpg

Saturday, November 25, 2017

Sharing Kindle content between Amazon household members

Amazon lets you create a "household" to share content, but it's really not obvious how you make kindle content from the other adult turn up on your kindle. Once you have created a household you need to go into each device under your devices section in the web app. There you can click a box to "show content from [insert other adult's name]". Then when you sync your phone kindle app or your physical kindle the books shared will show up. So you'll need to do that every time you want to read on a device.

Sunday, November 19, 2017

Adding a yubikey GPG key onto a new machine

If you are using a Yubikey encryption scheme and want to add the key onto a new system there's a few hoops to jump through. These instructions are for Ubuntu trusty.

First, get set up for using the yubikey:
sudo apt-get install gnupg-agent scdaemon pcscd pcsc-tools
you probably need to logout and back in. This post has extra setup, but I didn't have to do any of that, perhaps the gnome keyring badness has been fixed now.

Now check your yubikey is recognized:
pcsc_scan
gpg --card-status
Import the public key into the keyring and trust it:
gpg --import mykey_public_only.asc
gpg --expert --edit-key 123456
trust (set to ultimate)
save
You should now be good to go!


One more note: If you have multiple yubikeys for the same secret key and need to switch to using one of the other yubikeys I've had some problems with gpg wanting to see the card with the previous serial number, even if you delete the secret key. On the mac I found the easiest way to clean this up was to quit GPG Keychain and just remove the whole gnupg directory:
rm -rf ~/.gnupg
You should then be able to import the public key again and get it set up with the new yubikey by running:
gpg --card-status


Monday, October 23, 2017

Upgrading dd-wrt to protect against CVE-2017-14493

Google found, and worked with the dnsmasq author to fix, a bunch of vulnerabilities in dnsmasq. Now everyone needs to update tons of devices, including your router.

It's been a while since I updated this firmware so I had to figure it out from scratch again. AFAICT the procedure is to go find your router in the dd-wrt database. Hopefully it's supported. If it is you can go download the latest firmware from the ftp server and upload via the web interface. Anything later than 33430 should contain the fix.

Friday, May 26, 2017

Switching yubikeys

In this post I described how I set up gpg keys on a yubikey. Since I have multiple yubikeys for some redundancy I occasionally have to use a different one. This basically involves deleting the secret key and re-importing it from the yubikey.

On OSX


Open up GPG keychain and click through the scary warning to delete the secret keys. If you set it up right these are only stubs, the actual key is on the yubikey. Once you've done that, insert the key you want to use and get the stubs recreated with:
$ gpg --card-status

Tuesday, March 28, 2017

Managing go versions with gvm

gvm is a way to manage multiple go versions. It has some strange behaviour with go paths that I don't really understand. It essentially sets your GOPATH to a different directory for every version. You could just append your real go path, but it seems like there might be tooling that doesn't expect gopath to be a list. My solution was to:
gvm install go1.8
gvm use go1.8
gvm pkgenv
This pops $EDITOR which you can use to set your go path to $HOME/go. Check it with:
go env

Tuesday, January 10, 2017

kubectl Kubernetes Cheat Sheet

A complement to the official kubectl cheat sheet.

Getting kubectl

There's better ways to install it for permanent use, but here's a quick way for temporary use:
export PATH=/tmp:$PATH
cd /tmp; curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl; chmod 555 kubectl
Nodes
$ kubectl get nodes
$ kubectl get nodes/gke-hello-world-default-pool-9dbb0d2c-5qkl --show-labels
$ kubectl label nodes --all mylabel=myvalue
$ kubectl label nodes --all mylabel-

Namespaces

$ kubectl get all -n mynamespace
RBAC

What permissions do I have?
kubectl auth can-i --list
All clusterrolebindings:
kubectl get clusterrolebinding -o yaml
Role bindings for all namespaces:
kubectl get rolebinding --all-namespaces -o yaml
Privileges of current user:
kubectl create -f - -o yaml << EOF
apiVersion: authorization.k8s.io/v1
kind: SelfSubjectRulesReview      
spec:
  namespace: system
EOF

DaemonSet

Creating a daemonset:
$ echo 'apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: daemonset-example
spec:
  template:
    metadata:
      labels:
        app: daemonset-example
    spec:
      containers:
      - name: daemonset-example
        image: ubuntu:trusty
        command:
        - /bin/sh
        args:
        - -c
        - >-
          while [ true ]; do
          echo "DaemonSet running on $(hostname)" ;
          sleep 10 ;
          done
' | kubectl create -f -
$ kubectl delete daemonset daemonset-example

Get a shell in a container
$ kubectl run --rm=true -i --tty ubuntu --image=ubuntu -- /bin/bash
# Or with an existing container
$ kubectl exec -it shell-demo -- /bin/bash