Repository: osbuild/osbuild-composer
Pull request #1990 (2021-11-10 12:02:04)

ci: Send results to Coverity Scan daily
https://scan.coverity.com/projects/osbuild-osbuild-composer


This pull request includes:

- [ ] adequate testing for the new functionality or fixed issue
- [ ] adequate documentation informing people about the change such as
  - [ ] submit a PR for the [guides](https://github.com/osbuild/guides) repository if this PR changed any behavior described there: https://www.osbuild.org/guides/

<!--
Thanks for proposing a change to osbuild-composer!

Please don't remove the above check list. These are things that each pull
request must have before it is merged. It helps maintainers to not forget
anything.

If the reason for ticking any of the boxes is ambiguous, please add a short
note explaining why.

In addition, if this pull request fixes a downstream issue, please refer to
test/README.md and add these additional items:

- [ ] 1st commit of any `rhbz#` related PR contains bug reproducer; CI reports FAIL or
- [ ] PR contains automated tests for new functionality and
- [ ] QE has approved reproducer/new tests and
- [ ] Subsequent commits provide bug fixes without modifying the reproducer; CI reports PASS and
- [ ] QE approves this PR; RHBZ status is set to `MODIFIED + Verified=Tested`
-->



Patch:
diff --git a/.github/workflows/coverity_scan.yml b/.github/workflows/coverity_scan.yml
new file mode 100644
index 000000000..490696cd7
--- /dev/null
+++ b/.github/workflows/coverity_scan.yml
@@ -0,0 +1,38 @@
+name: Coverity Scan
+
+on:
+  # https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#scheduled-events
+  schedule:
+    - cron: '0 7 * * *' # Daily at 07:00 UTC
+
+jobs:
+  coverity_scan:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Clone repository
+        uses: actions/checkout@v2.3.4
+
+      # https://scan.coverity.com/projects/osbuild-osbuild-composer
+      - name: Run coverity scan script
+        env:
+          COVERITY_SCAN_PROJECT_NAME: "osbuild%2Fosbuild-composer"
+          COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
+          COVERITY_SCAN_EMAIL: ${{ secrets.COVERITY_SCAN_EMAIL }}
+        run: |
+          echo "Downloading coverity scan package."
+          curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64 \
+            --form project="$COVERITY_SCAN_PROJECT_NAME" \
+            --form token="$COVERITY_SCAN_TOKEN"
+          pushd /tmp && tar xzvf cov-analysis-linux64.tgz && popd
+
+          mkdir bin
+          /tmp/cov-analysis-linux64-*/bin/cov-build --dir cov-int go build -o bin/ ./...
+          tar czvf cov-int.tar.gz cov-int
+
+          echo "Uploading coverity scan result to http://scan.coverity.com"
+          curl https://scan.coverity.com/builds?project="$COVERITY_SCAN_PROJECT_NAME" \
+            --form token="$COVERITY_SCAN_TOKEN" \
+            --form email="$COVERITY_SCAN_EMAIL" \
+            --form file=@cov-int.tar.gz \
+            --form version="$(git rev-parse HEAD)" \
+            --form description="$GITHUB_REF / $GITHUB_SHA"
diff --git a/containers/fauxauth/fauxauth.py b/containers/fauxauth/fauxauth.py
new file mode 100755
index 000000000..6878890c1
--- /dev/null
+++ b/containers/fauxauth/fauxauth.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python3
+import argparse, subprocess
+
+def launch_server(address, port, certdir):
+  cmd = [
+      "/usr/libexec/osbuild-composer/osbuild-mock-openid-provider",
+      "-a", str.join(":", [address, port]),
+      "-rsaPubPem", f"{certdir}/client-crt.pem",
+      "-rsaPem", f"{certdir}/client-key.pem",
+  ]
+  print("Running oath server")
+  return subprocess.run(
+      cmd,
+      cwd="/usr/libexec/osbuild-composer",
+      stdin=subprocess.DEVNULL,
+      stderr=subprocess.STDOUT,
+  )
+
+def main():
+  parser = argparse.ArgumentParser()
+  parser.add_argument("-a", "--address", help="IP address for the server", type=str, default="localhost")
+  parser.add_argument("-p", "--port", help="Port for the server", type=str, default="8080")
+  parser.add_argument("-c", "--certdir", help="The location dir of the certs", type=str, default="/etc/osbuild-composer")
+  args = parser.parse_args()
+  launch_server(args.address, args.port, args.certdir)
+
+if __name__ == "__main__":
+  main()
diff --git a/distribution/Dockerfile-fauxauth b/distribution/Dockerfile-fauxauth
new file mode 100644
index 000000000..24337a6c9
--- /dev/null
+++ b/distribution/Dockerfile-fauxauth
@@ -0,0 +1,15 @@
+FROM registry.access.redhat.com/ubi8/go-toolset:latest AS builder
+COPY . .
+ENV GOFLAGS=-mod=vendor
+RUN go install ./cmd/osbuild-mock-openid-provider/
+
+FROM registry.access.redhat.com/ubi8/ubi-minimal:latest
+RUN microdnf install python3
+RUN mkdir -p "/usr/libexec/osbuild-composer"
+RUN mkdir -p "/etc/osbuild-composer/"
+
+COPY --from=builder /opt/app-root/src/go/bin/osbuild-mock-openid-provider /usr/libexec/osbuild-composer/
+COPY ./containers/fauxauth/fauxauth.py /opt/fauxauth.py
+
+EXPOSE 8080 8080
+ENTRYPOINT "/opt/fauxauth.py"
diff --git a/distribution/Dockerfile-worker b/distribution/Dockerfile-worker
index 663b5f87b..0b0036101 100644
--- a/distribution/Dockerfile-worker
+++ b/distribution/Dockerfile-worker
@@ -4,6 +4,7 @@ ENV GOFLAGS=-mod=vendor
 RUN go install ./cmd/osbuild-worker
 
 FROM fedora
+RUN dnf update -y && dnf upgrade -y
 RUN dnf install -y qemu-img osbuild osbuild-ostree
 RUN mkdir -p "/usr/libexec/osbuild-composer"
 RUN mkdir -p "/etc/osbuild-composer/"
diff --git a/internal/osbuild2/sshd_config_stage.go b/internal/osbuild2/sshd_config_stage.go
new file mode 100644
index 000000000..30d2afa4a
--- /dev/null
+++ b/internal/osbuild2/sshd_config_stage.go
@@ -0,0 +1,20 @@
+package osbuild2
+
+type SshdConfigConfig struct {
+	PasswordAuthentication          *bool `json:"PasswordAuthentication,omitempty"`
+	ChallengeResponseAuthentication *bool `json:"ChallengeResponseAuthentication,omitempty"`
+	ClientAliveInterval             *int  `json:"ClientAliveInterval,omitempty"`
+}
+
+type SshdConfigStageOptions struct {
+	Config SshdConfigConfig `json:"config"`
+}
+
+func (SshdConfigStageOptions) isStageOptions() {}
+
+func NewSshdConfigStage(options *SshdConfigStageOptions) *Stage {
+	return &Stage{
+		Type:    "org.osbuild.sshd.config",
+		Options: options,
+	}
+}
diff --git a/internal/osbuild2/stage.go b/internal/osbuild2/stage.go
index bc88dbdf4..6e6fc4bc0 100644
--- a/internal/osbuild2/stage.go
+++ b/internal/osbuild2/stage.go
@@ -146,6 +146,8 @@ func (stage *Stage) UnmarshalJSON(data []byte) error {
 		// The stage accepts also source input, but we need to rework all inputs first to handle this nicely here.
 		// Only files input is used by the XZ stage at this moment.
 		inputs = new(FilesInputs)
+	case "org.osbuild.sshd.config":
+		options = new(SshdConfigStageOptions)
 	default:
 		return fmt.Errorf("unexpected stage type: %s", rawStage.Type)
 	}


Test patch:
diff --git a/internal/osbuild2/sshd_config_stage_test.go b/internal/osbuild2/sshd_config_stage_test.go
new file mode 100644
index 000000000..f59d027b4
--- /dev/null
+++ b/internal/osbuild2/sshd_config_stage_test.go
@@ -0,0 +1,53 @@
+package osbuild2
+
+import (
+	"encoding/json"
+	"reflect"
+	"testing"
+
+	"github.com/osbuild/osbuild-composer/internal/common"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestNewSshdConfigStage(t *testing.T) {
+	expectedStage := &Stage{
+		Type:    "org.osbuild.sshd.config",
+		Options: &SshdConfigStageOptions{},
+	}
+	actualStage := NewSshdConfigStage(&SshdConfigStageOptions{})
+	assert.Equal(t, expectedStage, actualStage)
+}
+
+func TestJsonSshdConfigStage(t *testing.T) {
+	// First test that the JSON can be parsed into the expected structure.
+	expectedOptions := SshdConfigStageOptions{
+		Config: SshdConfigConfig{
+			PasswordAuthentication:          common.BoolToPtr(false),
+			ChallengeResponseAuthentication: common.BoolToPtr(false),
+			ClientAliveInterval:             common.IntToPtr(180),
+		},
+	}
+	inputString := `{
+		"config": {
+		  "PasswordAuthentication": false,
+		  "ChallengeResponseAuthentication": false,
+		  "ClientAliveInterval": 180
+		}
+	  }`
+	var inputOptions SshdConfigStageOptions
+	err := json.Unmarshal([]byte(inputString), &inputOptions)
+	assert.NoError(t, err, "failed to parse JSON into sshd config")
+	assert.True(t, reflect.DeepEqual(expectedOptions, inputOptions))
+
+	// Second try the other way around with stress on missing values
+	// for those parameters that the user didn't specify.
+	inputOptions = SshdConfigStageOptions{
+		Config: SshdConfigConfig{
+			PasswordAuthentication: common.BoolToPtr(true),
+		},
+	}
+	expectedString := `{"config":{"PasswordAuthentication":true}}`
+	inputBytes, err := json.Marshal(inputOptions)
+	assert.NoError(t, err, "failed to marshal sshd config into JSON")
+	assert.Equal(t, expectedString, string(inputBytes))
+}
diff --git a/internal/osbuild2/stage_test.go b/internal/osbuild2/stage_test.go
index 0789fcb34..bd318921c 100644
--- a/internal/osbuild2/stage_test.go
+++ b/internal/osbuild2/stage_test.go
@@ -637,6 +637,16 @@ func TestStage_UnmarshalJSON(t *testing.T) {
 				data: []byte(`{"type":"org.osbuild.users","options":{"users":null}}`),
 			},
 		},
+		{
+			name: "sshd.config",
+			fields: fields{
+				Type:    "org.osbuild.sshd.config",
+				Options: &SshdConfigStageOptions{},
+			},
+			args: args{
+				data: []byte(`{"type":"org.osbuild.sshd.config","options":{"config":{}}}`),
+			},
+		},
 	}
 	for idx, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {