Repository: osbuild/osbuild-composer
Pull request #2239 (2022-01-30 14:54:35)

jwt: support multiple key providers
We may need to use several SSO providers, so extend our
configuration to allow that.

Based on PoC from Sanne:

```
package main

import (
	"net/http"
	"log"

	"github.com/openshift-online/ocm-sdk-go/authentication"
	"github.com/openshift-online/ocm-sdk-go/logging"
)

type H struct{}

func (h *H) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	log.Println("HURRAY")
}

func main() {

	logBuilder := logging.NewGoLoggerBuilder()
	logger, err := logBuilder.Build()
	if err != nil {
		panic(err)
	}

	aH, err := authentication.NewHandler().
		KeysURL("https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/certs").
		KeysURL("https://identity.api.openshift.com/auth/realms/rhoas/protocol/openid-connect/certs").
			Logger(logger).Next(&H{}).Build()
	if err != nil {
		panic(err)
	}

	log.Fatal(http.ListenAndServe(":8080", aH))

}
```


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/.gitlab-ci.yml b/.gitlab-ci.yml
index 810c6d525..12cc8898d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -469,6 +469,7 @@ SCHEDULED_CLOUD_CLEANER:
     - terraform
   variables:
     RUNNER: aws/centos-stream-8-x86_64
+    INTERNAL_NETWORK: "true"
   rules:
     - if: '$CI_PIPELINE_SOURCE == "schedule" && $CLEANUP == "true"'
   script:
diff --git a/cmd/osbuild-composer/composer.go b/cmd/osbuild-composer/composer.go
index 89477a575..0aa17f7d6 100644
--- a/cmd/osbuild-composer/composer.go
+++ b/cmd/osbuild-composer/composer.go
@@ -220,8 +220,12 @@ func (c *Composer) Start() error {
 			handler := c.workers.Handler()
 			var err error
 			if c.config.Worker.EnableJWT {
+				keysURLs := c.config.Worker.JWTKeysURLs
+				if c.config.Worker.JWTKeysURL != "" {
+					keysURLs = append(keysURLs, c.config.Worker.JWTKeysURL)
+				}
 				handler, err = auth.BuildJWTAuthHandler(
-					c.config.Worker.JWTKeysURL,
+					keysURLs,
 					c.config.Worker.JWTKeysCA,
 					c.config.Worker.JWTACLFile,
 					[]string{
@@ -265,8 +269,12 @@ func (c *Composer) Start() error {
 			handler := http.Handler(mux)
 			var err error
 			if c.config.Koji.EnableJWT {
+				keysURLs := c.config.Koji.JWTKeysURLs
+				if c.config.Koji.JWTKeysURL != "" {
+					keysURLs = append(keysURLs, c.config.Koji.JWTKeysURL)
+				}
 				handler, err = auth.BuildJWTAuthHandler(
-					c.config.Koji.JWTKeysURL,
+					keysURLs,
 					c.config.Koji.JWTKeysCA,
 					c.config.Koji.JWTACLFile,
 					[]string{
diff --git a/cmd/osbuild-composer/config.go b/cmd/osbuild-composer/config.go
index 0881d8d58..4aa28a18c 100644
--- a/cmd/osbuild-composer/config.go
+++ b/cmd/osbuild-composer/config.go
@@ -25,6 +25,7 @@ type KojiAPIConfig struct {
 	EnableMTLS     bool      `toml:"enable_mtls"`
 	EnableJWT      bool      `toml:"enable_jwt"`
 	JWTKeysURL     string    `toml:"jwt_keys_url"`
+	JWTKeysURLs    []string  `toml:"jwt_keys_urls"`
 	JWTKeysCA      string    `toml:"jwt_ca_file"`
 	JWTACLFile     string    `toml:"jwt_acl_file"`
 	AWS            AWSConfig `toml:"aws_config"`
@@ -51,6 +52,7 @@ type WorkerAPIConfig struct {
 	EnableMTLS        bool     `toml:"enable_mtls"`
 	EnableJWT         bool     `toml:"enable_jwt"`
 	JWTKeysURL        string   `toml:"jwt_keys_url"`
+	JWTKeysURLs       []string `toml:"jwt_keys_urls"`
 	JWTKeysCA         string   `toml:"jwt_ca_file"`
 	JWTACLFile        string   `toml:"jwt_acl_file"`
 }
diff --git a/cmd/osbuild-mock-openid-provider/main.go b/cmd/osbuild-mock-openid-provider/main.go
index 941b4a5bb..2be1d7b23 100644
--- a/cmd/osbuild-mock-openid-provider/main.go
+++ b/cmd/osbuild-mock-openid-provider/main.go
@@ -21,11 +21,15 @@ func main() {
 	var rsaPem string
 	var tlsCert string
 	var tlsKey string
+	var tokenExpires int
+	var tokenScope string
 	flag.StringVar(&addr, "a", "localhost:8080", "Address to serve on")
 	flag.StringVar(&rsaPubPem, "rsaPubPem", "", "rsa pubkey in pem format (path)")
 	flag.StringVar(&rsaPem, "rsaPem", "", "rsa privkey in pem format (path)")
 	flag.StringVar(&tlsCert, "cert", "", "tls cert")
 	flag.StringVar(&tlsKey, "key", "", "tls key")
+	flag.IntVar(&tokenExpires, "expires", 60, "Expiration of the token in seconds (default: 360))")
+	flag.StringVar(&tokenScope, "scope", "", "The scope of the token (default: not set)")
 	flag.Parse()
 
 	if rsaPubPem == "" || rsaPem == "" {
@@ -102,12 +106,19 @@ func main() {
 			panic(err)
 		}
 
+		// See https://datatracker.ietf.org/doc/html/rfc6749
 		type response struct {
 			AccessToken string `json:"access_token"`
+			TokenType   string `json:"token_type"`           // required
+			ExpiresIn   int    `json:"expires_in,omitempty"` // lifetime in seconds
+			Scope       string `json:"scope,omitempty"`
 		}
 
 		err = json.NewEncoder(w).Encode(response{
 			AccessToken: tokenStr,
+			TokenType:   "Bearer",
+			ExpiresIn:   tokenExpires,
+			Scope:       tokenScope,
 		})
 		if err != nil {
 			panic(err)
diff --git a/internal/auth/jwt_auth_handler.go b/internal/auth/jwt_auth_handler.go
index 23eb98a1b..cfb49201b 100644
--- a/internal/auth/jwt_auth_handler.go
+++ b/internal/auth/jwt_auth_handler.go
@@ -15,7 +15,7 @@ import (
 
 // When using this handler for auth, it should be run as high up as possible.
 // Exceptions can be registered in the `exclude` slice
-func BuildJWTAuthHandler(keysURL, caFile, aclFile string, exclude []string, next http.Handler) (handler http.Handler, err error) {
+func BuildJWTAuthHandler(keysURLs []string, caFile, aclFile string, exclude []string, next http.Handler) (handler http.Handler, err error) {
 	logBuilder := logging.NewGoLoggerBuilder()
 	if caFile != "" {
 		logBuilder = logBuilder.Debug(true)
@@ -29,8 +29,11 @@ func BuildJWTAuthHandler(keysURL, caFile, aclFile string, exclude []string, next
 	logger.Info(context.Background(), aclFile)
 
 	builder := authentication.NewHandler().
-		Logger(logger).
-		KeysURL(keysURL)
+		Logger(logger)
+
+	for _, keysURL := range keysURLs {
+		builder = builder.KeysURL(keysURL)
+	}
 
 	// Used during testing
 	if caFile != "" {
diff --git a/internal/distro/rhel86/partition_tables.go b/internal/distro/rhel86/partition_tables.go
index aa088d0f2..ed465a590 100644
--- a/internal/distro/rhel86/partition_tables.go
+++ b/internal/distro/rhel86/partition_tables.go
@@ -155,7 +155,7 @@ var ec2BasePartitionTables = distro.BasePartitionTableMap{
 				},
 			},
 			{
-				Size: 1048676,
+				Size: 1048576,
 				Type: disk.FilesystemDataGUID,
 				UUID: disk.FilesystemDataUUID,
 				Filesystem: &disk.Filesystem{
diff --git a/schutzbot/scheduled_cloud_cleaner.sh b/schutzbot/scheduled_cloud_cleaner.sh
index 2cf440def..c1963e50e 100755
--- a/schutzbot/scheduled_cloud_cleaner.sh
+++ b/schutzbot/scheduled_cloud_cleaner.sh
@@ -276,3 +276,38 @@ for image in $IMAGES; do
                 echo "deleted image: ${NAME}"        
 	fi
 done
+
+
+#---------------------------------------------------------------
+#                       vmware cleanup
+#---------------------------------------------------------------
+
+greenprint "starting vmware cleanup"
+
+GOVC_CMD=/tmp/govc
+
+# We need govc to talk to vSphere
+if ! hash govc; then
+    greenprint "Installing govc"
+    pushd /tmp || exit
+        curl -Ls --retry 5 --output govc.gz \
+            https://github.com/vmware/govmomi/releases/download/v0.24.0/govc_linux_amd64.gz
+        gunzip -f govc.gz
+        chmod +x /tmp/govc
+        $GOVC_CMD version
+    popd || exit
+fi
+
+GOVC_AUTH="${GOVMOMI_USERNAME}:${GOVMOMI_PASSWORD}@${GOVMOMI_URL}"
+
+TAGGED=$($GOVC_CMD tags.attached.ls -u "${GOVC_AUTH}" -k "gitlab-ci-test" | xargs -r ${GOVC_CMD} ls -u "${GOVC_AUTH}" -k -L)
+
+for vm in $TAGGED; do
+	# Could use JSON output, but it takes much longer, as it includes more properties
+	CREATION_TIME=$($GOVC_CMD vm.info -u "${GOVC_AUTH}" -k "${vm}" | awk '$1 ~ /^ *Boot/ { print $3 " " $4 $5 }')
+	
+	if [[ $(date -d "${CREATION_TIME}" +%s) -lt ${DELETE_TIME} ]]; then
+                $GOVC_CMD vm.destroy -u "${GOVC_AUTH}" -k "${vm}"
+                echo "destroyed vm: ${vm}"
+	fi
+done


Test patch:
diff --git a/test/cases/vmware.sh b/test/cases/vmware.sh
index f1e921085..ac60b418a 100755
--- a/test/cases/vmware.sh
+++ b/test/cases/vmware.sh
@@ -196,6 +196,12 @@ $GOVC_CMD vm.create -u "${GOVMOMI_USERNAME}":"${GOVMOMI_PASSWORD}"@"${GOVMOMI_UR
     --disk.controller=ide \
     "${IMAGE_KEY}"
 
+# tagging vm as testing object
+$GOVC_CMD tags.attach -u "${GOVMOMI_USERNAME}":"${GOVMOMI_PASSWORD}"@"${GOVMOMI_URL}" \
+    -k=true \
+    -c "osbuild-composer testing" gitlab-ci-test \
+    "/${GOVMOMI_DATACENTER}/vm/${GOVMOMI_FOLDER}/${IMAGE_KEY}"
+
 greenprint "Getting IP of created VM"
 VM_IP=$($GOVC_CMD vm.ip -u "${GOVMOMI_USERNAME}":"${GOVMOMI_PASSWORD}"@"${GOVMOMI_URL}" -k=true "${IMAGE_KEY}")
 
diff --git a/test/data/manifests/centos_8-aarch64-ami-boot.json b/test/data/manifests/centos_8-aarch64-ami-boot.json
index 0b269616a..acf5f4e70 100644
--- a/test/data/manifests/centos_8-aarch64-ami-boot.json
+++ b/test/data/manifests/centos_8-aarch64-ami-boot.json
@@ -1101,14 +1101,14 @@
                   "uuid": "68B2905B-DF3E-4FB3-80FA-49D1E773AA33"
                 },
                 {
-                  "size": 1048676,
+                  "size": 1048576,
                   "start": 411648,
                   "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
                   "uuid": "CB07C243-BC44-4717-853E-28852021225B"
                 },
                 {
-                  "size": 19511096,
-                  "start": 1460324,
+                  "size": 19511196,
+                  "start": 1460224,
                   "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
                   "uuid": "6264D520-3FB9-423F-8AB8-7A0A8E3D3562"
                 }
@@ -1150,7 +1150,7 @@
                 "options": {
                   "filename": "image.raw",
                   "start": 411648,
-                  "size": 1048676
+                  "size": 1048576
                 }
               }
             }
@@ -1166,8 +1166,8 @@
                 "type": "org.osbuild.loopback",
                 "options": {
                   "filename": "image.raw",
-                  "start": 1460324,
-                  "size": 19511096
+                  "start": 1460224,
+                  "size": 19511196
                 }
               }
             }
@@ -1197,7 +1197,7 @@
                 "options": {
                   "filename": "image.raw",
                   "start": 411648,
-                  "size": 1048676
+                  "size": 1048576
                 }
               },
               "efi": {
@@ -1212,8 +1212,8 @@
                 "type": "org.osbuild.loopback",
                 "options": {
                   "filename": "image.raw",
-                  "start": 1460324,
-                  "size": 19511096
+                  "start": 1460224,
+                  "size": 19511196
                 }
               }
             },
diff --git a/test/data/manifests/rhel_86-aarch64-ami-boot.json b/test/data/manifests/rhel_86-aarch64-ami-boot.json
index 37f811681..4b0090907 100644
--- a/test/data/manifests/rhel_86-aarch64-ami-boot.json
+++ b/test/data/manifests/rhel_86-aarch64-ami-boot.json
@@ -1128,14 +1128,14 @@
                   "uuid": "68B2905B-DF3E-4FB3-80FA-49D1E773AA33"
                 },
                 {
-                  "size": 1048676,
+                  "size": 1048576,
                   "start": 411648,
                   "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
                   "uuid": "CB07C243-BC44-4717-853E-28852021225B"
                 },
                 {
-                  "size": 19511096,
-                  "start": 1460324,
+                  "size": 19511196,
+                  "start": 1460224,
                   "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
                   "uuid": "6264D520-3FB9-423F-8AB8-7A0A8E3D3562"
                 }
@@ -1177,7 +1177,7 @@
                 "options": {
                   "filename": "image.raw",
                   "start": 411648,
-                  "size": 1048676
+                  "size": 1048576
                 }
               }
             }
@@ -1193,8 +1193,8 @@
                 "type": "org.osbuild.loopback",
                 "options": {
                   "filename": "image.raw",
-                  "start": 1460324,
-                  "size": 19511096
+                  "start": 1460224,
+                  "size": 19511196
                 }
               }
             }
@@ -1224,7 +1224,7 @@
                 "options": {
                   "filename": "image.raw",
                   "start": 411648,
-                  "size": 1048676
+                  "size": 1048576
                 }
               },
               "efi": {
@@ -1239,8 +1239,8 @@
                 "type": "org.osbuild.loopback",
                 "options": {
                   "filename": "image.raw",
-                  "start": 1460324,
-                  "size": 19511096
+                  "start": 1460224,
+                  "size": 19511196
                 }
               }
             },
diff --git a/test/data/manifests/rhel_86-aarch64-ec2-boot.json b/test/data/manifests/rhel_86-aarch64-ec2-boot.json
index 71bd2af49..a0904bc31 100644
--- a/test/data/manifests/rhel_86-aarch64-ec2-boot.json
+++ b/test/data/manifests/rhel_86-aarch64-ec2-boot.json
@@ -1142,14 +1142,14 @@
                   "uuid": "68B2905B-DF3E-4FB3-80FA-49D1E773AA33"
                 },
                 {
-                  "size": 1048676,
+                  "size": 1048576,
                   "start": 411648,
                   "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
                   "uuid": "CB07C243-BC44-4717-853E-28852021225B"
                 },
                 {
-                  "size": 19511096,
-                  "start": 1460324,
+                  "size": 19511196,
+                  "start": 1460224,
                   "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4",
                   "uuid": "6264D520-3FB9-423F-8AB8-7A0A8E3D3562"
                 }
@@ -1191,7 +1191,7 @@
                 "options": {
                   "filename": "image.raw",
                   "start": 411648,
-                  "size": 1048676
+                  "size": 1048576
                 }
               }
             }
@@ -1207,8 +1207,8 @@
                 "type": "org.osbuild.loopback",
                 "options": {
                   "filename": "image.raw",
-                  "start": 1460324,
-                  "size": 19511096
+                  "start": 1460224,
+                  "size": 19511196
                 }
               }
             }
@@ -1238,7 +1238,7 @@
                 "options": {
                   "filename": "image.raw",
                   "start": 411648,
-                  "size": 1048676
+                  "size": 1048576
                 }
               },
               "efi": {
@@ -1253,8 +1253,8 @@
                 "type": "org.osbuild.loopback",
                 "options": {
                   "filename": "image.raw",
-                  "start": 1460324,
-                  "size": 19511096
+                  "start": 1460224,
+                  "size": 19511196
                 }
               }
             },