How to generate an Android SBOM per build with Github Actions

If you’d like to generate an Android SBOM every time you build your app, you can combine previous techniques discussed on this blog to achieve this with GitHub Actions + NowSecure. If you’re not a NowSecure customer, first sign up for 10 free SBOMs so you can follow along in the tutorial.

To brush up on the previous techniques, check out my blog+video on how to generate an Android SBOM in CycloneDX format. This article will walk you though setting up your environment, building a React Native Android app, generating a list of dependencies with gradle and and finally how to generate a CycloneDX SBOM with binary analysis leveraging NowSecure Platform.

We can then leverage the above techniques to automatically generate an Android SBOM each time you update your mobile app.

1. Code setup

For this demo, we’ll change from a React Native Android app in previous tutorials to a more traditional Java + Kotlin app. K-9 Mail is a popular open source Android email app that’s been around since at least 2008 (initial commits) and in active development. You can find it on both F-Droid as well as the Play Store.

Fork and clone repo

While you could perform all changed needed directly in the GitHub UI, I prefer to work locally and then push changes. So, let’s fork the k-9 repo into your own account and then swap out ahoog42 for your GitHub username:

$ mkdir -p ~/spfexpert; cd ~/spfexpert
$ git clone git@github.com:ahoog42/k-9.git
$ cd k-9

Enable GitHub Dependency Graph

By default, a forked repo will not automatically enable GitHub’s Dependency Graph which is needed for the Dependency Submission API (and so you can see the dependencies!). To enable it, you’ll simply navigate to:

GitHub repo -> Insights -> Dependency Graph

and then click the green “Enable the dependency graph” button.

Build app locally (optional)

K-9 maintains a # How to build K-9 Mail article which is always worth taking a look at. The highlights are:

  • Targets Java 8 but for command line builds, use Java 11
  • Android SDK Build-tools 30.0.3
  • SDK Platform 30

For this example, we’re just going to build the debug version of the app so we don’t have to mess around with signing keys. If you wanted to test it out on your computer, make sure you have Java 11 installed and then:

$ ./gradlew assembleDebug

which should build the app and store it at:

ls -lh app/k9mail/build/outputs/apk/debug/
total 27424
-rw-r--r--  1 hiro  staff    13M Nov  7 08:31 k9mail-debug.apk
-rw-r--r--  1 hiro  staff   385B Nov  7 08:31 output-metadata.json

2. Configure NowSecure: Mobile SBOM Action

Now we’ll create a new GitHub action that will build the debug version of the app and run the NowSecure: Mobile SBOM GitHub Action to generate an SBOM via binary analysis and submit it to the repo’s Dependency Graph via the beta Dependency Submission API.

Obtain NowSecure token and group_id

Once you have access to NowSecure (see free trial link above), you’ll need to generate an API JWT token and then determine your app’s group id.

NowSecure JWT Token

First, you’ll log in to NowSecure Platform and then (step-by-step documented in “Creating an API Bearer Token in Platform”):

User Profile (upper right) -> Tokens -> Add token name -> Generate -> Copy token

From there, you’ll add the token as a secret in the forked K-9 repo:

Configure GitHub Action Secrets Settings -> Secrets -> Actions -> New Repository Secret

And then put NS_TOKEN in as the name and the paste in the copied token from above. You can now securely access your NowSecure Platform token in your GitHub Action workflows.

NowSecure app group id

Similarly, let’s find out our default app group id in NowSecure Platform (see also “Where can I find the GroupID for the API?”):

Apps -> Select App -> Package Details

and they click the copy icon next to the app group (e.g. Auto Group). Go ahead and stash the copied UUID somewhere so you can paste it into the workflow yml below.

Configure workflow

To configure the NowSecure Mobile SBOM GitHub Action, you create a .yml file under .github\workflows. GitHub has great documentation on the workflow syntax. We generally create a file called .github\workflows\nowsecure-sbom.yml. Key configuration includes:

  • name - what to call the action
  • on - when to do it (workflow_dispatch is really handy for testing)
  • jobs - these are the specific steps your workflow needs, often:
    • build the app
    • upload to NowSecure and kick off an assessment
    • process NowSecure Platform results
    • upload SBOM to Dependency Graph
$ vim .github/workflows/nowsecure-sbom.yml
$ git add .github/workflows/nowsecure-sbom.yml
$ git commit .github/workflows/nowsecure-sbom.yml -m 'add NowSecure Mobile SBOM Action'
$ git push

Below is a nowsecure-sbom.yml file for building the K-9 Mail which you could easily adapt for your build process. For the group_id at the end of the yml, make sure you copy the group uuid from the previous step.

name: "NowSecure SBOM"

on:
  workflow_dispatch:
    branches: [ main ]
  # can add push and pull_request here 

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Install Java
        uses: actions/setup-java@v2
        with:
          java-version: "11"
          distribution: "adopt"
          cache: "gradle"

      - name: Validate Gradle wrapper
        uses: gradle/wrapper-validation-action@v1
        
      - name: Build application
        run: ./gradlew assembleDebug --stacktrace --no-daemon

      - name: Upload application
        uses: actions/upload-artifact@v2
        with:
          name: app
          path: ./app/k9mail/build/outputs/apk/debug/k9mail-debug.apk
          retention-days: 3

  scan:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
        
      - name: Download application
        uses: actions/download-artifact@v2
        with:
          name: app
          
      - name: NowSecure-SBOM
        uses: nowsecure/nowsecure-sbom-action@v1
        timeout-minutes: 60
        with:
          token: ${{ secrets.NS_TOKEN }}
          app_file: k9mail-debug.apk
          group_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxx"

Run NowSecure Mobile SBOM

Now that we have the GitHub Action workflow configured, we can simply head to the GitHub rep UI and do the following:

Actions -> NowSecure SBOM -> Run Workflow Dropdown -> Run Workflow

Run GitHub Action manually with workflow_dispatch

The workflow will then kick off the build process, then upload the binary to NowSecure Platform for analysis and lastly will pull the SBOM results back into the Dependency Graph (this can take 15-30 mins since we also perform dynamic analysis on the mobile app binary).

After the workflow completes, you can view the full list of dependencies in your repo’s dependency graph:

GitHub repo -> Insights -> Dependency Graph

SBOM in GitHub Dependency Graph Since we’re using binary analysis, the results will be grouped by the source in which the dependency was found. In this screenshot, you can see there are multiple dex files and we can see dependencies from core Android (kotlin), okio from Square, Apache and more.