G204 doesn't necessarily indicate a bad behaviour. But could help discover potential command injection vector.
220 lines
5.6 KiB
Go
220 lines
5.6 KiB
Go
// This command contains some tests for the koji integration. It's a bit
|
|
// different from the other cmd/*-tests executables because it cannot be
|
|
// currently run as a "base test". Instead, it's run as a part of the
|
|
// koji.sh test because it needs a working Koji instance to pass.
|
|
|
|
// +build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"io"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"os"
|
|
"os/exec"
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/osbuild/osbuild-composer/internal/rpmmd"
|
|
"github.com/osbuild/osbuild-composer/internal/upload/koji"
|
|
)
|
|
|
|
func TestKojiRefund(t *testing.T) {
|
|
shareDir := "/tmp/osbuild-composer-koji-test"
|
|
server := "https://localhost:4343/kojihub"
|
|
|
|
// base our transport on the default one
|
|
transport := http.DefaultTransport.(*http.Transport).Clone()
|
|
|
|
// use the self-signed certificate generated by run-koji-container
|
|
certPool := x509.NewCertPool()
|
|
cert, err := ioutil.ReadFile(shareDir + "/ca-crt.pem")
|
|
require.NoError(t, err)
|
|
|
|
ok := certPool.AppendCertsFromPEM(cert)
|
|
require.True(t, ok)
|
|
|
|
transport.TLSClientConfig = &tls.Config{
|
|
RootCAs: certPool,
|
|
MinVersion: tls.VersionTLS12,
|
|
}
|
|
|
|
// login
|
|
credentials := &koji.GSSAPICredentials{
|
|
Principal: "osbuild-krb@LOCAL",
|
|
KeyTab: shareDir + "/client.keytab",
|
|
}
|
|
k, err := koji.NewFromGSSAPI(server, credentials, transport)
|
|
require.NoError(t, err)
|
|
|
|
defer func() {
|
|
err := k.Logout()
|
|
if err != nil {
|
|
require.NoError(t, err)
|
|
}
|
|
}()
|
|
|
|
initResult, err := k.CGInitBuild("name", "verison", "release")
|
|
require.NoError(t, err)
|
|
|
|
err = k.CGCancelBuild(initResult.BuildID, initResult.Token)
|
|
require.NoError(t, err)
|
|
|
|
err = k.CGCancelBuild(initResult.BuildID, initResult.Token)
|
|
require.Error(t, err)
|
|
|
|
initResult, err = k.CGInitBuild("name", "verison", "release")
|
|
require.NoError(t, err)
|
|
|
|
err = k.CGFailBuild(initResult.BuildID, initResult.Token)
|
|
require.NoError(t, err)
|
|
|
|
err = k.CGFailBuild(initResult.BuildID, initResult.Token)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
func TestKojiImport(t *testing.T) {
|
|
// define constants
|
|
server := "https://localhost:4343/kojihub"
|
|
filename := "image.qcow2"
|
|
filesize := 1024
|
|
shareDir := "/tmp/osbuild-composer-koji-test"
|
|
// you cannot create two build with a same name, let's create a random one each time
|
|
buildName := "osbuild-image-" + uuid.Must(uuid.NewRandom()).String()
|
|
// koji needs to specify a directory to which the upload should happen, let's reuse the build name
|
|
uploadDirectory := buildName
|
|
|
|
// base our transport on the default one
|
|
transport := http.DefaultTransport.(*http.Transport).Clone()
|
|
|
|
// use the self-signed certificate generated by run-koji-container
|
|
certPool := x509.NewCertPool()
|
|
cert, err := ioutil.ReadFile(shareDir + "/ca-crt.pem")
|
|
require.NoError(t, err)
|
|
|
|
ok := certPool.AppendCertsFromPEM(cert)
|
|
require.True(t, ok)
|
|
|
|
transport.TLSClientConfig = &tls.Config{
|
|
RootCAs: certPool,
|
|
MinVersion: tls.VersionTLS12,
|
|
}
|
|
|
|
// login
|
|
credentials := &koji.GSSAPICredentials{
|
|
Principal: "osbuild-krb@LOCAL",
|
|
KeyTab: shareDir + "/client.keytab",
|
|
}
|
|
k, err := koji.NewFromGSSAPI(server, credentials, transport)
|
|
require.NoError(t, err)
|
|
|
|
defer func() {
|
|
err := k.Logout()
|
|
if err != nil {
|
|
require.NoError(t, err)
|
|
}
|
|
}()
|
|
|
|
// Create a random file
|
|
f, err := ioutil.TempFile("", "osbuild-koji-test-*.qcow2")
|
|
require.NoError(t, err)
|
|
defer func() {
|
|
assert.NoError(t, f.Close())
|
|
assert.NoError(t, os.Remove(f.Name()))
|
|
}()
|
|
|
|
_, err = io.CopyN(f, rand.Reader, int64(filesize))
|
|
require.NoError(t, err)
|
|
_, err = f.Seek(0, io.SeekStart)
|
|
require.NoError(t, err)
|
|
|
|
// Upload the file
|
|
hash, _, err := k.Upload(f, uploadDirectory, filename)
|
|
require.NoError(t, err)
|
|
|
|
// Import the build
|
|
build := koji.ImageBuild{
|
|
TaskID: 1,
|
|
Name: buildName,
|
|
Version: "1",
|
|
Release: "1",
|
|
StartTime: time.Now().Unix(),
|
|
EndTime: time.Now().Unix(),
|
|
}
|
|
buildRoots := []koji.BuildRoot{
|
|
{
|
|
ID: 1,
|
|
Host: koji.Host{
|
|
Os: "RHEL8",
|
|
Arch: "noarch",
|
|
},
|
|
ContentGenerator: koji.ContentGenerator{
|
|
Name: "osbuild",
|
|
Version: "1",
|
|
},
|
|
Container: koji.Container{
|
|
Type: "nspawn",
|
|
Arch: "noarch",
|
|
},
|
|
Tools: []koji.Tool{},
|
|
RPMs: []rpmmd.RPM{},
|
|
},
|
|
}
|
|
output := []koji.Image{
|
|
{
|
|
BuildRootID: 1,
|
|
Filename: filename,
|
|
FileSize: uint64(filesize),
|
|
Arch: "noarch",
|
|
ChecksumType: "md5",
|
|
MD5: hash,
|
|
Type: "image",
|
|
RPMs: []rpmmd.RPM{},
|
|
Extra: koji.ImageExtra{
|
|
Info: koji.ImageExtraInfo{
|
|
Arch: "noarch",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
initResult, err := k.CGInitBuild(build.Name, build.Version, build.Release)
|
|
require.NoError(t, err)
|
|
|
|
build.BuildID = uint64(initResult.BuildID)
|
|
|
|
importResult, err := k.CGImport(build, buildRoots, output, uploadDirectory, initResult.Token)
|
|
require.NoError(t, err)
|
|
|
|
// check if the build is really there:
|
|
// There's no potential command injection vector here
|
|
/* #nosec G204 */
|
|
cmd := exec.Command(
|
|
"koji",
|
|
"--server", server,
|
|
"-c", "/usr/share/tests/osbuild-composer/koji/koji.conf",
|
|
"--keytab", credentials.KeyTab,
|
|
"--principal", credentials.Principal,
|
|
"list-builds",
|
|
"--buildid", strconv.Itoa(importResult.BuildID),
|
|
)
|
|
|
|
// sample output:
|
|
// Build Built by State
|
|
// ------------------------------------------------------- ---------------- ----------------
|
|
// osbuild-image-92882b90-4bd9-4422-8b8a-40863f94535a-1-1 osbuild COMPLETE
|
|
out, err := cmd.CombinedOutput()
|
|
assert.NoError(t, err)
|
|
|
|
// let's check for COMPLETE, koji will exit with non-zero status code if the build doesn't exist
|
|
assert.Contains(t, string(out), "COMPLETE")
|
|
}
|