Skip to content

Commit 2e1e47e

Browse files
dual gpgkey per repo support in rpm emt distro (#511)
* dual gpgkey per repo support in rpm emt distro
1 parent 827968b commit 2e1e47e

File tree

11 files changed

+206
-35
lines changed

11 files changed

+206
-35
lines changed

config/osv/edge-microvisor-toolkit/emt3/providerconfigs/x86_64_repo.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ component: "emt3.0-base" # Repository component/section identifier
77
gpgCheck: true # Enabled with Intel GPG key
88
repoGPGCheck: true # Enabled with Intel GPG key
99
enabled: true
10-
gpgKey: "https://raw.githubusercontent.com/open-edge-platform/edge-microvisor-toolkit/refs/heads/3.0/SPECS/edge-repos/INTEL-RPM-GPG-KEY"
10+
gpgKeys:
11+
- "https://raw.githubusercontent.com/open-edge-platform/edge-microvisor-toolkit/refs/heads/3.0/SPECS/edge-repos/INTEL-RPM-GPG-KEY"
12+
- "https://raw.githubusercontent.com/cheeyanglee/edge-microvisor-toolkit/e2e05b402c056bbf4ba1a429490b3c37f4d659d7/SPECS/edge-repos/INTEL-RPM-GPG-KEY-26"
1113
# Repository configuration URL (for reference): https://raw.githubusercontent.com/open-edge-platform/edge-microvisor-toolkit/refs/heads/3.0/SPECS/edge-repos/edge-base.repo
1214
buildPath: "./builds/emt3" # Will be replaced with temp_dir/builds/emt3 at runtime

image-templates/azl3-x86_64-dlstreamer.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ packageRepositories:
3838

3939
- codename: "edge-base"
4040
url: "https://files-rs.edgeorchestration.intel.com/files-edge-orch/microvisor/rpms/3.0/base"
41-
pkey: "https://raw.githubusercontent.com/open-edge-platform/edge-microvisor-toolkit/refs/heads/3.0/SPECS/edge-repos/INTEL-RPM-GPG-KEY" # Uncomment and replace in real config
41+
pkeys:
42+
- "https://raw.githubusercontent.com/open-edge-platform/edge-microvisor-toolkit/refs/heads/3.0/SPECS/edge-repos/INTEL-RPM-GPG-KEY"
43+
- "https://raw.githubusercontent.com/cheeyanglee/edge-microvisor-toolkit/e2e05b402c056bbf4ba1a429490b3c37f4d659d7/SPECS/edge-repos/INTEL-RPM-GPG-KEY-26"
4244

4345
- codename: "OpenVINO"
4446
url: "https://yum.repos.intel.com/openvino/"
@@ -95,6 +97,7 @@ systemConfig:
9597
- ffmpeg
9698
- gstreamer
9799
- opencv
100+
- util-linux-devel-2.40.2-3.emt3
98101
- intel-dlstreamer-2025.2.0
99102
- openvino-2025.3.0
100103
- linux-firmware-i915

image-templates/emt3-x86_64-ptl-emf-raw.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ packageRepositories:
2929
- codename: "emtNext"
3030
priority: 1001
3131
url: "https://files-rs.edgeorchestration.intel.com/files-edge-orch/microvisor/rpms/next/base"
32-
pkey: "https://raw.githubusercontent.com/open-edge-platform/edge-microvisor-toolkit/refs/heads/3.0/SPECS/edge-repos/INTEL-RPM-GPG-KEY"
32+
pkeys:
33+
- "https://raw.githubusercontent.com/open-edge-platform/edge-microvisor-toolkit/refs/heads/3.0/SPECS/edge-repos/INTEL-RPM-GPG-KEY"
34+
- "https://raw.githubusercontent.com/cheeyanglee/edge-microvisor-toolkit/e2e05b402c056bbf4ba1a429490b3c37f4d659d7/SPECS/edge-repos/INTEL-RPM-GPG-KEY-26"
3335
# list of allowed packages from this repository
3436
allowPackages:
3537
- kernel-6.17.11

image-templates/emt3-x86_64-ptl-emf-rt-raw.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ target:
3030
packageRepositories:
3131
- codename: "emtNext"
3232
url: "https://files-rs.edgeorchestration.intel.com/files-edge-orch/microvisor/rpms/next/base"
33-
pkey: "https://raw.githubusercontent.com/open-edge-platform/edge-microvisor-toolkit/refs/heads/3.0/SPECS/edge-repos/INTEL-RPM-GPG-KEY"
33+
pkeys:
34+
- "https://raw.githubusercontent.com/open-edge-platform/edge-microvisor-toolkit/refs/heads/3.0/SPECS/edge-repos/INTEL-RPM-GPG-KEY"
35+
- "https://raw.githubusercontent.com/cheeyanglee/edge-microvisor-toolkit/e2e05b402c056bbf4ba1a429490b3c37f4d659d7/SPECS/edge-repos/INTEL-RPM-GPG-KEY-26"
3436
# list of allowed packages from this repository
3537
allowPackages:
3638
- kernel-rt-6.17.11

image-templates/rcd10-x86_64-dlstreamer.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ packageRepositories:
1515

1616
- codename: "edge-base"
1717
url: "https://files-rs.edgeorchestration.intel.com/files-edge-orch/microvisor/rpms/3.0/base"
18-
pkey: "https://raw.githubusercontent.com/open-edge-platform/edge-microvisor-toolkit/refs/heads/3.0/SPECS/edge-repos/INTEL-RPM-GPG-KEY" # Uncomment and replace in real config
18+
pkeys:
19+
- "https://raw.githubusercontent.com/open-edge-platform/edge-microvisor-toolkit/refs/heads/3.0/SPECS/edge-repos/INTEL-RPM-GPG-KEY"
20+
- "https://raw.githubusercontent.com/cheeyanglee/edge-microvisor-toolkit/e2e05b402c056bbf4ba1a429490b3c37f4d659d7/SPECS/edge-repos/INTEL-RPM-GPG-KEY-26"
1921
allowPackages:
2022
- kernel-drivers-gpu
2123
- kernel

internal/config/apt_sources_integration_test.go

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,32 @@ import (
77
"testing"
88
)
99

10+
func createLocalTestGPGKey(t *testing.T, pattern string) string {
11+
t.Helper()
12+
13+
tempFile, err := os.CreateTemp("", pattern)
14+
if err != nil {
15+
t.Fatalf("Failed to create local test GPG key file: %v", err)
16+
}
17+
18+
if _, err := tempFile.WriteString("dummy-gpg-key-content"); err != nil {
19+
tempFile.Close()
20+
os.Remove(tempFile.Name())
21+
t.Fatalf("Failed to write local test GPG key file: %v", err)
22+
}
23+
24+
if err := tempFile.Close(); err != nil {
25+
os.Remove(tempFile.Name())
26+
t.Fatalf("Failed to close local test GPG key file: %v", err)
27+
}
28+
29+
t.Cleanup(func() {
30+
_ = os.Remove(tempFile.Name())
31+
})
32+
33+
return tempFile.Name()
34+
}
35+
1036
// resolveAdditionalFilePath converts relative paths (like ../../../../../../tmp/file.gpg)
1137
// to absolute paths by joining with working directory or config root
1238
func resolveAdditionalFilePath(relativePath string) (string, error) {
@@ -38,6 +64,8 @@ func resolveAdditionalFilePath(relativePath string) (string, error) {
3864

3965
// TestIntegrationAptSourcesGeneration tests the complete flow
4066
func TestIntegrationAptSourcesGeneration(t *testing.T) {
67+
sedKeyPath := createLocalTestGPGKey(t, "sed-test-key-*.gpg")
68+
openvinoKeyPath := createLocalTestGPGKey(t, "openvino-test-key-*.gpg")
4169
// Create a realistic test template similar to the example
4270
template := &ImageTemplate{
4371
Image: ImageInfo{
@@ -54,14 +82,14 @@ func TestIntegrationAptSourcesGeneration(t *testing.T) {
5482
{
5583
Codename: "sed",
5684
URL: "https://eci.intel.com/sed-repos/noble",
57-
PKey: "https://eci.intel.com/sed-repos/gpg-keys/GPG-PUB-KEY-INTEL-SED.gpg",
85+
PKey: sedKeyPath,
5886
Priority: 1000,
5987
Component: "",
6088
},
6189
{
6290
Codename: "ubuntu24",
6391
URL: "https://apt.repos.intel.com/openvino/2025",
64-
PKey: "https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB",
92+
PKey: openvinoKeyPath,
6593
Component: "main contrib",
6694
},
6795
},
@@ -132,6 +160,8 @@ func TestIntegrationAptSourcesGeneration(t *testing.T) {
132160

133161
// TestIntegrationAptPreferencesGeneration tests the complete flow including preferences
134162
func TestIntegrationAptPreferencesGeneration(t *testing.T) {
163+
sedKeyPath := createLocalTestGPGKey(t, "sed-test-key-*.gpg")
164+
openvinoKeyPath := createLocalTestGPGKey(t, "openvino-test-key-*.gpg")
135165
// Create a realistic test template with priorities
136166
template := &ImageTemplate{
137167
Image: ImageInfo{
@@ -149,14 +179,14 @@ func TestIntegrationAptPreferencesGeneration(t *testing.T) {
149179
ID: "sed-repo",
150180
Codename: "sed",
151181
URL: "https://eci.intel.com/sed-repos/noble",
152-
PKey: "https://eci.intel.com/sed-repos/gpg-keys/GPG-PUB-KEY-INTEL-SED.gpg",
182+
PKey: sedKeyPath,
153183
Priority: 1000,
154184
},
155185
{
156186
ID: "openvino-repo",
157187
Codename: "ubuntu24",
158188
URL: "https://apt.repos.intel.com/openvino/2025",
159-
PKey: "https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB",
189+
PKey: openvinoKeyPath,
160190
Component: "main contrib",
161191
Priority: 500,
162192
},

internal/config/config.go

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -47,26 +47,28 @@ type PackageRepository struct {
4747
Codename string `yaml:"codename"` // Repository identifier/codename
4848
URL string `yaml:"url"` // Repository base URL
4949
PKey string `yaml:"pkey"` // Public GPG key URL for verification
50+
PKeys []string `yaml:"pkeys,omitempty"` // Multiple public GPG key URLs for verification
5051
Component string `yaml:"component,omitempty"` // Repository component (e.g., "main", "restricted")
5152
Priority int `yaml:"priority,omitempty"` // Repository priority (higher numbers = higher priority)
5253
AllowPackages []string `yaml:"allowPackages,omitempty"` // Optional: specific packages to include from this repo (pinning)
5354
}
5455

5556
// ProviderRepoConfig represents the repository configuration for a provider
5657
type ProviderRepoConfig struct {
57-
Name string `yaml:"name"`
58-
Type string `yaml:"type"` // Repository type: "rpm" or "deb"
59-
BaseURL string `yaml:"baseURL"`
60-
PkgPrefix string `yaml:"pkgPrefix"`
61-
ReleaseFile string `yaml:"releaseFile"`
62-
ReleaseSign string `yaml:"releaseSign"`
63-
PbGPGKey string `yaml:"pbGPGKey"` // For DEB repositories (eLxr)
64-
GPGKey string `yaml:"gpgKey"` // For RPM repositories (azl, emt)
65-
GPGCheck bool `yaml:"gpgCheck"`
66-
RepoGPGCheck bool `yaml:"repoGPGCheck"`
67-
Enabled bool `yaml:"enabled"`
68-
Component string `yaml:"component"` // Repository component/section identifier
69-
BuildPath string `yaml:"buildPath"`
58+
Name string `yaml:"name"`
59+
Type string `yaml:"type"` // Repository type: "rpm" or "deb"
60+
BaseURL string `yaml:"baseURL"`
61+
PkgPrefix string `yaml:"pkgPrefix"`
62+
ReleaseFile string `yaml:"releaseFile"`
63+
ReleaseSign string `yaml:"releaseSign"`
64+
PbGPGKey string `yaml:"pbGPGKey"` // For DEB repositories (eLxr)
65+
GPGKey string `yaml:"gpgKey"` // For RPM repositories (azl, emt)
66+
GPGKeys []string `yaml:"gpgKeys,omitempty"`
67+
GPGCheck bool `yaml:"gpgCheck"`
68+
RepoGPGCheck bool `yaml:"repoGPGCheck"`
69+
Enabled bool `yaml:"enabled"`
70+
Component string `yaml:"component"` // Repository component/section identifier
71+
BuildPath string `yaml:"buildPath"`
7072
}
7173

7274
// ProviderRepoConfigs represents multiple repository configurations for a provider
@@ -864,13 +866,26 @@ func (prc *ProviderRepoConfig) ToRepoConfigData(arch string) (repoType, name, ur
864866
url = prc.BaseURL
865867
}
866868

867-
// Handle GPG key URL construction
868-
gpgKey = prc.GPGKey
869-
if !strings.HasPrefix(gpgKey, "http") && gpgKey != "" {
870-
// For relative GPG key paths, use the constructed repository URL
871-
gpgKey = fmt.Sprintf("%s/%s", url, gpgKey)
869+
gpgKeyValues := make([]string, 0, len(prc.GPGKeys)+1)
870+
if len(prc.GPGKeys) > 0 {
871+
gpgKeyValues = append(gpgKeyValues, prc.GPGKeys...)
872+
}
873+
if prc.GPGKey != "" {
874+
gpgKeyValues = append(gpgKeyValues, prc.GPGKey)
875+
}
876+
877+
resolvedKeys := make([]string, 0, len(gpgKeyValues))
878+
for _, keyURL := range gpgKeyValues {
879+
keyURL = strings.TrimSpace(keyURL)
880+
if keyURL == "" {
881+
continue
882+
}
883+
if !strings.HasPrefix(keyURL, "http") {
884+
keyURL = fmt.Sprintf("%s/%s", url, keyURL)
885+
}
886+
resolvedKeys = append(resolvedKeys, keyURL)
872887
}
873-
// If gpgKey starts with http, use it as-is
888+
gpgKey = strings.Join(resolvedKeys, ",")
874889

875890
// DEB-specific fields are empty for RPM
876891
pkgPrefix = ""

internal/config/config_test.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3665,6 +3665,7 @@ func TestUnifiedRepoConfig(t *testing.T) {
36653665
arch string
36663666
expectedType string
36673667
expectedURL string
3668+
expectedGPG string
36683669
}{
36693670
{
36703671
name: "RPM Repository (Azure Linux)",
@@ -3679,6 +3680,7 @@ func TestUnifiedRepoConfig(t *testing.T) {
36793680
arch: "x86_64",
36803681
expectedType: "rpm",
36813682
expectedURL: "https://packages.microsoft.com/azurelinux/3.0/prod/base/x86_64",
3683+
expectedGPG: "https://packages.microsoft.com/azurelinux/3.0/prod/base/x86_64/repodata/repomd.xml.key",
36823684
},
36833685
{
36843686
name: "DEB Repository (eLxr)",
@@ -3710,6 +3712,21 @@ func TestUnifiedRepoConfig(t *testing.T) {
37103712
expectedType: "rpm",
37113713
expectedURL: "https://files-rs.edgeorchestration.intel.com/files-edge-orch/microvisor/rpm/3.0",
37123714
},
3715+
{
3716+
name: "RPM Repository with multiple GPG keys",
3717+
repoConfig: ProviderRepoConfig{
3718+
Name: "Edge Microvisor Toolkit 3.0",
3719+
Type: "rpm",
3720+
BaseURL: "https://files-rs.edgeorchestration.intel.com/files-edge-orch/microvisor/rpm/3.0",
3721+
GPGKeys: []string{"https://example.com/key-old.asc", "https://example.com/key-new.asc"},
3722+
Component: "emt3.0-base",
3723+
Enabled: true,
3724+
},
3725+
arch: "x86_64",
3726+
expectedType: "rpm",
3727+
expectedURL: "https://files-rs.edgeorchestration.intel.com/files-edge-orch/microvisor/rpm/3.0",
3728+
expectedGPG: "https://example.com/key-old.asc,https://example.com/key-new.asc",
3729+
},
37133730
}
37143731

37153732
for _, tt := range tests {
@@ -3749,7 +3766,11 @@ func TestUnifiedRepoConfig(t *testing.T) {
37493766
}
37503767

37513768
// Verify arch substitution in GPG key if applicable
3752-
if tt.repoConfig.GPGKey != "" && gpgKey != "" {
3769+
if tt.expectedGPG != "" {
3770+
if gpgKey != tt.expectedGPG {
3771+
t.Errorf("Expected GPG key %s, got %s", tt.expectedGPG, gpgKey)
3772+
}
3773+
} else if tt.repoConfig.GPGKey != "" && gpgKey != "" {
37533774
expectedGPGKey := tt.repoConfig.GPGKey
37543775
if expectedGPGKey == "repodata/repomd.xml.key" {
37553776
expectedGPGKey = "https://packages.microsoft.com/azurelinux/3.0/prod/base/x86_64/repodata/repomd.xml.key"

internal/config/schema/os-image-template.schema.json

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,24 @@
332332
}
333333
]
334334
},
335+
"pkeys": {
336+
"type": "array",
337+
"description": "Multiple public GPG key URLs for package verification (alternative to pkey)",
338+
"items": {
339+
"type": "string",
340+
"oneOf": [
341+
{
342+
"pattern": "^(https?|file)://",
343+
"description": "URL to GPG key file (must start with http://, https://, or file://)"
344+
},
345+
{
346+
"pattern": "^/",
347+
"description": "Absolute local file path to GPG key file"
348+
}
349+
]
350+
},
351+
"minItems": 1
352+
},
335353
"component": {
336354
"type": "string",
337355
"description": "Repository component (e.g., 'main', 'restricted')",
@@ -354,7 +372,11 @@
354372
}
355373
}
356374
},
357-
"required": ["codename", "url", "pkey"],
375+
"required": ["codename", "url"],
376+
"anyOf": [
377+
{ "required": ["pkey"] },
378+
{ "required": ["pkeys"] }
379+
],
358380
"additionalProperties": false
359381
},
360382

0 commit comments

Comments
 (0)