API testing with Yaade and Hoppscotch

Published: May 30, 2024 by Isaac Johnson

I became aware of Yaade from a Marius Hosting writeup on launching Yaade with Portainer in Docker.

Today, we will install Yaade with a Kubernetes manifest and show how we can configure it. We’ll test it against an AWX instance and show how to solve Basic auth. We’ll set up users and show how to save queries into collections.

We’ll also compare it to Hoppscotch.io and the Hoppscotch.com fat client.

Yaade

Manifest YAML

$ cat manifest.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: yaade-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: yaade-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: yaade
  template:
    metadata:
      labels:
        app: yaade
    spec:
      containers:
        - name: yaade
          image: esperotech/yaade:latest
          ports:
            - containerPort: 9339
          env:
            - name: YAADE_ADMIN_USERNAME
              value: admin
          volumeMounts:
            - name: yaade-volume
              mountPath: /app/data
      volumes:
        - name: yaade-volume
          persistentVolumeClaim:
            claimName: yaade-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: yaade-service
spec:
  selector:
    app: yaade
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 9339
  type: NodePort

Testing

$ kubectl apply -f manifest.yaml
persistentvolumeclaim/yaade-pvc created
deployment.apps/yaade-deployment created
service/yaade-service created

I can see the pods are up and the service has allocated a nodeport

$ kubectl get pods -l app=yaade
NAME                                READY   STATUS    RESTARTS   AGE
yaade-deployment-84f9b4c4cb-zs4cd   1/1     Running   0          24s


$ kubectl get svc yaade-service
NAME            TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
yaade-service   NodePort   10.43.10.72   <none>        80:30784/TCP   46s

Which I can see is running

/content/images/2024/05/yaade-01.png

I can login with “admin” and “password”

/content/images/2024/05/yaade-02.png

Add the Extension

/content/images/2024/05/yaade-03.png

and set the hostname on the extension to our Yaade instance

/content/images/2024/05/yaade-04.png

I couldn’t get it to do anything however.

Let’s try a public ingress to see if that unblocks us.

Ingress

I’ll create a quick A Record

$ az account set --subscription "Pay-As-You-Go" && az network dns record-set a add-record -g idjdnsrg -z tpk.pw -a 75.73.224.240 -n

I can create an Ingress YAML and apply it

$ cat ./yaade.ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: azuredns-tpkpw
    ingress.kubernetes.io/ssl-redirect: "true"
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  name: yaade-ingress
spec:
  rules:
  - host: yaade.tpk.pw
    http:
      paths:
      - backend:
          service:
            name: yaade-service
            port:
              number: 80
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - yaade.tpk.pw
    secretName: yaade-tls

$ kubectl apply -f ./yaade.ingress.yaml
ingress.networking.k8s.io/yaade-ingress created

When I saw the cert was satisfied

$ kubectl get cert yaade-tls
NAME        READY   SECRET      AGE
yaade-tls   True    yaade-tls   8m20s

I could then login

/content/images/2024/05/yaade-05.png

I then updated the Chrome extension

/content/images/2024/05/yaade-06.png

I first tried a public endpoint, the one I use for AWX. This isn’t a REST endpoint, just a webpage I know will be there.

/content/images/2024/05/yaade-07.png

While the /api/v2 was public, trying to query an endpoint (properly) stopped me due to lack of auth

/content/images/2024/05/yaade-08.png

I was trying to figure out how to pass basic login information when it dawned on me we can just use the Authorization header. The key is “Authorization” and the value is “Basic xxxxx” where xxxxx is the base64 encoded username and password. I got that with:

$ echo 'admin:MYPASSWORD' | tr -d '\n' | base64

/content/images/2024/05/yaade-09.png

Now I can do authenticated endpoints.

However, every test of internal endpoints (while I’m outside my network) was a fail

/content/images/2024/05/yaade-10.png

Admin pass

I can change my password in settings

/content/images/2024/05/yaade-12.png

Users

We can add and edit uses in the settings area under Users

/content/images/2024/05/yaade-11.png

Note: you cannot set the password. It will just be “password”. Thus, the next step should be to fire up an Incognito browser and set the password

/content/images/2024/05/yaade-13.png

I wanted to test permanence, so i killed the current pod and tried to login again

builder@LuiGi:~/Workspaces/codeserver$ kubectl get pods  | grep yaa
yaade-deployment-84f9b4c4cb-zs4cd                    1/1     Running            0                  22h
builder@LuiGi:~/Workspaces/codeserver$ kubectl delete pod yaade-deployment-84f9b4c4cb-zs4cd
pod "yaade-deployment-84f9b4c4cb-zs4cd" deleted
builder@LuiGi:~/Workspaces/codeserver$ kubectl delete pod yaade-deployment-84f9b4c4cb-zs4cd
Error from server (NotFound): pods "yaade-deployment-84f9b4c4cb-zs4cd" not found
builder@LuiGi:~/Workspaces/codeserver$ kubectl get pods  | grep yaa
yaade-deployment-84f9b4c4cb-f8sss                    1/1     Running            0                  9s

Logging in, I can confirm, used the updated passwords.

Backups

You can backup and restore collections, users, etc using the Backup section of settings

/content/images/2024/05/yaade-14.png

Collections

I can create a new collection

/content/images/2024/05/yaade-16.png

Then create a query and save it. The save icon is quite small:

/content/images/2024/05/yaade-15.png

The idea is we can build them all out in a collection

/content/images/2024/05/yaade-17.png

Hopscotch

We can create an account

/content/images/2024/05/yaade-18.png

I can then test in my own workspace

/content/images/2024/05/yaade-19.png

I can use the same credentials as before

/content/images/2024/05/yaade-20.png

I can create a collection

/content/images/2024/05/yaade-21.png

And save the query

/content/images/2024/05/yaade-22.png

Realtime queries

We can do realtime queries

/content/images/2024/05/yaade-23.png

We can also do GraphQL

/content/images/2024/05/yaade-24.png

Enterprise

Everything Hoppscotch.io is open source, Hoppscotch.com is the commercial site

/content/images/2024/05/yaade-25.png

Client

We can download the Client

/content/images/2024/05/yaade-26.png

And run queries from our desktop

/content/images/2024/05/yaade-27.png

Open Source

Hopscotch has all their source here https://github.com/hoppscotch

Who

It’s oddly hard to find out who is behind Hoppscotch. Even the about page has boilerplate Lorem Ipsum text

/content/images/2024/05/yaade-28.png

The About page on hoppscotch.io simply states “Hoppscotch was founded by Liyas Thomas (CEO) and Andrew Bastin (CTO) in 2019.”.

Summary

In both the notes on Yaade and from some oauth login URLs I can tell Hoppscotch is based on Firebase (GCP). There seems little to no info on upgrading or buying a commercial product save for the sister site of Hoppscotch.com. I’m not flagging this as bad - just different. From what I can see on Linked in, the CTO co-founded the company before he enrolled in University.

As for Yaade, it’s interesting. I’m not sold on the need, per se, but I can also say that I’ll probably use it from time to time. I think running it as a local container makes a lot of sense.

Yaade Hoppscotch OpenSource Containers Kubernetes

Have something to add? Feedback? You can use the feedback form

Isaac Johnson

Isaac Johnson

Cloud Solutions Architect

Isaac is a CSA and DevOps engineer who focuses on cloud migrations and devops processes. He also is a dad to three wonderful daughters (hence the references to Princess King sprinkled throughout the blog).

Theme built by C.S. Rhymes