Repository: osbuild/osbuild-composer
Pull request #1857 (2021-09-30 13:27:09)

Enable jwt disable tls

teg: Could we make jwt and TLS independent of each other? Not entirely sure if that makes sense, but in principle you could combine them in any way, right?
teg: mTLS and JWT should probably be mutually exclusive and error out if you enable both...
Gundersanne: > mTLS and JWT should probably be mutually exclusive and error out if you enable both...

Is an extra option for mtls really required? Like currently there's 2 options for auth so...

Patch:
diff --git a/NEWS.md b/NEWS.md
index 85346d4f6..e97f494bb 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,3 +1,22 @@
+## CHANGES WITH 35:
+
+  * Change filesystem minsize from int, which is platform dependent, to uint64
+  * Fix a bug in the startup of composer where e.g. Plymouth would leave it hanging
+  * RHEL-9.0: Use qcow2 compat 1.1
+  * RHEL-9.0: Re-add `nss-altfiles` which is needed for OSTree based systems
+  * RHEL-9.0: Add `gnome-kiosk` package and switch to `python3` from `python36`
+  * RHEL-8.5: Set bootloader to `none` for Edge raw images
+  * Improve logging for the Cloud API
+  * Return a 500 error and write to log on middleware panic
+  * Return a 400 error when deleting an unknown source in the weldr API
+
+Contributions from: Achilleas Koutsou, Alexander Todorov, Brian C. Lane,
+                    Christian Kellner, Diaa Sami, Gianluca Zuccarelli, Jakub Rusz,
+                    Martin Sehnoutka, Ondřej Budai, Sanne Raymaekers,
+                    Simon Steinbeiss, Tomas Hozza
+
+— Vöcklabruck, 2021-09-30
+
 ## CHANGES WITH 34:
 
   * Support temporary AWS credentials
diff --git a/cmd/osbuild-composer/composer.go b/cmd/osbuild-composer/composer.go
index 670720546..2c07a5d8e 100644
--- a/cmd/osbuild-composer/composer.go
+++ b/cmd/osbuild-composer/composer.go
@@ -104,10 +104,20 @@ func (c *Composer) InitWeldr(repoPaths []string, weldrListener net.Listener,
 	return nil
 }
 
-func (c *Composer) InitAPI(cert, key string, enableJWT bool, l net.Listener) error {
+func (c *Composer) InitAPI(cert, key string, enableTLS bool, enableMTLS bool, enableJWT bool, l net.Listener) error {
 	c.api = cloudapi.NewServer(c.workers, c.rpm, c.distros)
 	c.koji = kojiapi.NewServer(c.logger, c.workers, c.rpm, c.distros)
 
+	if !enableTLS {
+		c.apiListener = l
+		return nil
+	}
+
+	// If both are off or both are on, error out
+	if enableJWT == enableMTLS {
+		return fmt.Errorf("API: Either mTLS or JWT authentication must be enabled")
+	}
+
 	clientAuth := tls.RequireAndVerifyClientCert
 	if enableJWT {
 		// jwt enabled => tls listener without client auth
@@ -133,7 +143,17 @@ func (c *Composer) InitLocalWorker(l net.Listener) {
 	c.localWorkerListener = l
 }
 
-func (c *Composer) InitRemoteWorkers(cert, key string, enableJWT bool, l net.Listener) error {
+func (c *Composer) InitRemoteWorkers(cert, key string, enableTLS bool, enableMTLS bool, enableJWT bool, l net.Listener) error {
+	if !enableTLS {
+		c.workerListener = l
+		return nil
+	}
+
+	// If both are off or both are on, error out
+	if enableJWT == enableMTLS {
+		return fmt.Errorf("Remote worker API: Either mTLS or JWT authentication must be enabled")
+	}
+
 	clientAuth := tls.RequireAndVerifyClientCert
 	if enableJWT {
 		// jwt enabled => tls listener without client auth
@@ -227,11 +247,11 @@ func (c *Composer) Start() error {
 
 			handler := http.Handler(mux)
 			var err error
-			if c.config.ComposerAPI.EnableJWT {
+			if c.config.Koji.EnableJWT {
 				handler, err = auth.BuildJWTAuthHandler(
-					c.config.ComposerAPI.JWTKeysURL,
-					c.config.ComposerAPI.JWTKeysCA,
-					c.config.ComposerAPI.JWTACLFile,
+					c.config.Koji.JWTKeysURL,
+					c.config.Koji.JWTKeysCA,
+					c.config.Koji.JWTACLFile,
 					[]string{
 						"/metrics/?$",
 					}, mux)
diff --git a/cmd/osbuild-composer/config.go b/cmd/osbuild-composer/config.go
index 7dc5bc3b4..3e3043316 100644
--- a/cmd/osbuild-composer/config.go
+++ b/cmd/osbuild-composer/config.go
@@ -10,32 +10,38 @@ import (
 )
 
 type ComposerConfigFile struct {
-	Koji struct {
-		AllowedDomains []string `toml:"allowed_domains"`
-		CA             string   `toml:"ca"`
-	} `toml:"koji"`
-	Worker struct {
-		AllowedDomains []string `toml:"allowed_domains"`
-		CA             string   `toml:"ca"`
-		PGHost         string   `toml:"pg_host" env:"PGHOST"`
-		PGPort         string   `toml:"pg_port" env:"PGPORT"`
-		PGDatabase     string   `toml:"pg_database" env:"PGDATABASE"`
-		PGUser         string   `toml:"pg_user" env:"PGUSER"`
-		PGPassword     string   `toml:"pg_password" env:"PGPASSWORD"`
-		PGSSLMode      string   `toml:"pg_ssl_mode" env:"PGSSLMODE"`
-		EnableJWT      bool     `toml:"enable_jwt"`
-		JWTKeysURL     string   `toml:"jwt_keys_url"`
-		JWTKeysCA      string   `toml:"jwt_ca_file"`
-		JWTACLFile     string   `toml:"jwt_acl_file"`
-	} `toml:"worker"`
-	ComposerAPI struct {
-		EnableJWT  bool   `toml:"enable_jwt"`
-		JWTKeysURL string `toml:"jwt_keys_url"`
-		JWTKeysCA  string `toml:"jwt_ca_file"`
-		JWTACLFile string `toml:"jwt_acl_file"`
-	} `toml:"composer_api"`
-	WeldrAPI WeldrAPIConfig `toml:"weldr_api"`
-	logLevel string         `toml:"log_level"`
+	Koji     KojiAPIConfig   `toml:"koji"`
+	Worker   WorkerAPIConfig `toml:"worker"`
+	WeldrAPI WeldrAPIConfig  `toml:"weldr_api"`
+	LogLevel string          `toml:"log_level"`
+}
+
+type KojiAPIConfig struct {
+	AllowedDomains []string `toml:"allowed_domains"`
+	CA             string   `toml:"ca"`
+	EnableTLS      bool     `toml:"enable_tls"`
+	EnableMTLS     bool     `toml:"enable_mtls"`
+	EnableJWT      bool     `toml:"enable_jwt"`
+	JWTKeysURL     string   `toml:"jwt_keys_url"`
+	JWTKeysCA      string   `toml:"jwt_ca_file"`
+	JWTACLFile     string   `toml:"jwt_acl_file"`
+}
+
+type WorkerAPIConfig struct {
+	AllowedDomains []string `toml:"allowed_domains"`
+	CA             string   `toml:"ca"`
+	PGHost         string   `toml:"pg_host" env:"PGHOST"`
+	PGPort         string   `toml:"pg_port" env:"PGPORT"`
+	PGDatabase     string   `toml:"pg_database" env:"PGDATABASE"`
+	PGUser         string   `toml:"pg_user" env:"PGUSER"`
+	PGPassword     string   `toml:"pg_password" env:"PGPASSWORD"`
+	PGSSLMode      string   `toml:"pg_ssl_mode" env:"PGSSLMODE"`
+	EnableTLS      bool     `toml:"enable_tls"`
+	EnableMTLS     bool     `toml:"enable_mtls"`
+	EnableJWT      bool     `toml:"enable_jwt"`
+	JWTKeysURL     string   `toml:"jwt_keys_url"`
+	JWTKeysCA      string   `toml:"jwt_ca_file"`
+	JWTACLFile     string   `toml:"jwt_acl_file"`
 }
 
 type WeldrAPIConfig struct {
@@ -65,6 +71,16 @@ func (c *ComposerConfigFile) weldrDistrosImageTypeDenyList() map[string][]string
 // - 'ec2' and 'ec2-ha' image types on 'rhel-85' are not exposed via Weldr API
 func GetDefaultConfig() *ComposerConfigFile {
 	return &ComposerConfigFile{
+		Koji: KojiAPIConfig{
+			EnableTLS:  true,
+			EnableMTLS: true,
+			EnableJWT:  false,
+		},
+		Worker: WorkerAPIConfig{
+			EnableTLS:  true,
+			EnableMTLS: true,
+			EnableJWT:  false,
+		},
 		WeldrAPI: WeldrAPIConfig{
 			map[string]WeldrDistroConfig{
 				"rhel-*": {
diff --git a/cmd/osbuild-composer/main.go b/cmd/osbuild-composer/main.go
index 1fce3e92a..87f130096 100644
--- a/cmd/osbuild-composer/main.go
+++ b/cmd/osbuild-composer/main.go
@@ -40,7 +40,7 @@ func main() {
 	}
 
 	logrus.SetOutput(os.Stdout)
-	logLevel, err := logrus.ParseLevel(config.logLevel)
+	logLevel, err := logrus.ParseLevel(config.LogLevel)
 
 	if err == nil {
 		logrus.SetLevel(logLevel)
@@ -98,7 +98,7 @@ func main() {
 			logrus.Fatal("The osbuild-composer-api.socket unit is misconfigured. It should contain only one socket.")
 		}
 
-		err = composer.InitAPI(ServerCertFile, ServerKeyFile, config.ComposerAPI.EnableJWT, l[0])
+		err = composer.InitAPI(ServerCertFile, ServerKeyFile, config.Koji.EnableTLS, config.Koji.EnableMTLS, config.Koji.EnableJWT, l[0])
 		if err != nil {
 			logrus.Fatalf("Error initializing koji API: %v", err)
 		}
@@ -109,7 +109,7 @@ func main() {
 			logrus.Fatal("The osbuild-remote-worker.socket unit is misconfigured. It should contain only one socket.")
 		}
 
-		err = composer.InitRemoteWorkers(ServerCertFile, ServerKeyFile, config.Worker.EnableJWT, l[0])
+		err = composer.InitRemoteWorkers(ServerCertFile, ServerKeyFile, config.Worker.EnableTLS, config.Worker.EnableMTLS, config.Worker.EnableJWT, l[0])
 		if err != nil {
 			logrus.Fatalf("Error initializing worker API: %v", err)
 		}
diff --git a/osbuild-composer.spec b/osbuild-composer.spec
index 1f1b23223..d36a3889f 100644
--- a/osbuild-composer.spec
+++ b/osbuild-composer.spec
@@ -4,7 +4,7 @@
 
 %global goipath         github.com/osbuild/osbuild-composer
 
-Version:        34
+Version:        35
 
 %gometa
 


Test patch:
diff --git a/cmd/osbuild-composer/config_test.go b/cmd/osbuild-composer/config_test.go
index 88957b8ac..57afe76f2 100644
--- a/cmd/osbuild-composer/config_test.go
+++ b/cmd/osbuild-composer/config_test.go
@@ -23,13 +23,24 @@ func TestNonExisting(t *testing.T) {
 
 func TestDefaultConfig(t *testing.T) {
 	defaultConfig := GetDefaultConfig()
-	require.Empty(t, defaultConfig.Koji)
-	require.Empty(t, defaultConfig.Worker)
-	require.False(t, defaultConfig.ComposerAPI.EnableJWT)
-	require.Equal(t, "", defaultConfig.ComposerAPI.JWTKeysCA)
+
+	require.False(t, defaultConfig.Koji.EnableJWT)
+	require.Equal(t, "", defaultConfig.Koji.JWTKeysCA)
 	require.False(t, defaultConfig.Worker.EnableJWT)
 	require.Equal(t, "", defaultConfig.Worker.JWTKeysCA)
 
+	require.Equal(t, KojiAPIConfig{
+		EnableTLS:  true,
+		EnableMTLS: true,
+		EnableJWT:  false,
+	}, defaultConfig.Koji)
+
+	require.Equal(t, WorkerAPIConfig{
+		EnableTLS:  true,
+		EnableMTLS: true,
+		EnableJWT:  false,
+	}, defaultConfig.Worker)
+
 	expectedWeldrAPIConfig := WeldrAPIConfig{
 		DistroConfigs: map[string]WeldrDistroConfig{
 			"rhel-*": {
@@ -66,10 +77,10 @@ func TestConfig(t *testing.T) {
 	require.NotNil(t, config)
 	require.Equal(t, "composer-db", config.Worker.PGDatabase)
 
-	require.True(t, config.ComposerAPI.EnableJWT)
-	require.Equal(t, "https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/certs", config.ComposerAPI.JWTKeysURL)
-	require.Equal(t, "", config.ComposerAPI.JWTKeysCA)
-	require.Equal(t, "/var/lib/osbuild-composer/acl", config.ComposerAPI.JWTACLFile)
+	require.False(t, config.Koji.EnableJWT)
+	require.Equal(t, "https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/certs", config.Koji.JWTKeysURL)
+	require.Equal(t, "", config.Koji.JWTKeysCA)
+	require.Equal(t, "/var/lib/osbuild-composer/acl", config.Koji.JWTACLFile)
 }
 
 func TestWeldrDistrosImageTypeDenyList(t *testing.T) {
diff --git a/cmd/osbuild-composer/testdata/test.toml b/cmd/osbuild-composer/testdata/test.toml
index 28163c9c5..218d98671 100644
--- a/cmd/osbuild-composer/testdata/test.toml
+++ b/cmd/osbuild-composer/testdata/test.toml
@@ -1,6 +1,9 @@
 [koji]
 allowed_domains = [ "osbuild.org" ]
 ca = "/etc/osbuild-composer/ca-crt.pem"
+enable_jwt = false
+jwt_keys_url = "https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/certs"
+jwt_acl_file = "/var/lib/osbuild-composer/acl"
 
 [worker]
 allowed_domains = [ "osbuild.org" ]
@@ -15,8 +18,3 @@ image_type_denylist = [ "qcow2" ]
 
 # overrides the default rhel-* configuration
 [weldr_api.distros."rhel-*"]
-
-[composer_api]
-enable_jwt = true
-jwt_keys_url = "https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/certs"
-jwt_acl_file = "/var/lib/osbuild-composer/acl"
diff --git a/test/cases/api.sh b/test/cases/api.sh
index 5bf3f070d..1297463b9 100755
--- a/test/cases/api.sh
+++ b/test/cases/api.sh
@@ -1157,26 +1157,24 @@ sudo mv -f /usr/libexec/osbuild-composer/dnf-json.bak /usr/libexec/osbuild-compo
 #
 cat <<EOF | sudo tee "/etc/osbuild-composer/osbuild-composer.toml"
 [koji]
-allowed_domains = [ "localhost", "client.osbuild.org" ]
-ca = "/etc/osbuild-composer/ca-crt.pem"
-
+enable_tls = false
+enable_mtls = false
+enable_jwt = true
+jwt_keys_url = "https://localhost:8080/certs"
+jwt_ca_file = "/etc/osbuild-composer/ca-crt.pem"
+jwt_acl_file = ""
 [worker]
-allowed_domains = [ "localhost", "worker.osbuild.org" ]
-ca = "/etc/osbuild-composer/ca-crt.pem"
 pg_host = "localhost"
 pg_port = "5432"
 pg_database = "osbuildcomposer"
 pg_user = "postgres"
 pg_password = "foobar"
 pg_ssl_mode = "disable"
+enable_tls = false
+enable_mtls = false
 enable_jwt = true
 jwt_keys_url = "https://localhost:8080/certs"
 jwt_ca_file = "/etc/osbuild-composer/ca-crt.pem"
-[composer_api]
-enable_jwt = true
-jwt_keys_url = "https://localhost:8080/certs"
-jwt_ca_file = "/etc/osbuild-composer/ca-crt.pem"
-jwt_acl_file = ""
 EOF
 
 cat <<EOF | sudo tee "/etc/osbuild-worker/token"
@@ -1205,21 +1203,19 @@ TOKEN="$(curl localhost:8081/token | jq -r .access_token)"
 
 [ "$(curl \
         --silent \
-        --cacert /etc/osbuild-composer/ca-crt.pem \
         --output /dev/null \
         --write-out '%{http_code}' \
         --header "Authorization: Bearer $TOKEN" \
-        https://localhost/api/composer/v1/version)" = "200" ]
+        http://localhost:443/api/composer/v1/version)" = "200" ]
 
 [ "$(curl \
         --silent \
-        --cacert /etc/osbuild-composer/ca-crt.pem \
         --output /dev/null \
         --write-out '%{http_code}' \
         --header "Authorization: Bearer badtoken" \
-        https://localhost/api/composer/v1/version)" = "401" ]
+        http://localhost:443/api/composer/v1/version)" = "401" ]
 
-sudo systemctl start osbuild-remote-worker@https:--localhost:8700.service
-sudo systemctl is-active --quiet osbuild-remote-worker@https:--localhost:8700.service
+sudo systemctl start osbuild-remote-worker@http:--localhost:8700.service
+sudo systemctl is-active --quiet osbuild-remote-worker@http:--localhost:8700.service
 
 exit 0