Skip to content

Commit 6ab5da8

Browse files
committed
MCO-2110: Migrate security tests
1 parent 6d48b64 commit 6ab5da8

18 files changed

Lines changed: 3116 additions & 41 deletions

cmd/machine-config-tests-ext/main.go

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,6 @@ func applyLabelFilters(specs et.ExtensionTestSpecs) {
4141
}
4242
}
4343
})
44-
45-
// Exclude tests with "Exclude:REASON" labels
46-
specs.Walk(func(spec *et.ExtensionTestSpec) {
47-
for label := range spec.Labels {
48-
if strings.HasPrefix(label, "Exclude:") {
49-
spec.Exclude("true")
50-
}
51-
}
52-
})
5344
}
5445

5546
func main() {
@@ -92,6 +83,12 @@ func main() {
9283
panic(fmt.Sprintf("couldn't build extension test specs from ginkgo: %+v", err.Error()))
9384
}
9485

86+
// Exclude tests with "Exclude:REASON" labels
87+
specs = specs.MustFilter([]string{
88+
`!labels.exists(l, l.startsWith("Exclude:"))`,
89+
})
90+
91+
// Configure environment flags filters
9592
applyLabelFilters(specs)
9693

9794
ext.AddSpecs(specs)

test/extended-priv/configmap.go

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
o "github.com/onsi/gomega"
88
exutil "github.com/openshift/machine-config-operator/test/extended-priv/util"
9+
logger "github.com/openshift/machine-config-operator/test/extended-priv/util/logext"
910
)
1011

1112
// ConfigMap struct encapsulates the functionalities regarding ocp configmaps
@@ -28,7 +29,23 @@ func NewConfigMapList(oc *exutil.CLI, namespace string) *ConfigMapList {
2829
return &ConfigMapList{ResourceList: *NewNamespacedResourceList(oc, "ConfigMap", namespace)}
2930
}
3031

31-
// GetDataValue returns the value of a specific key in the .data field
32+
// HasKey returns if a key is present in "data"
33+
func (cm *ConfigMap) HasKey(key string) (string, bool, error) {
34+
dataMap, err := cm.GetDataMap()
35+
36+
if err != nil {
37+
return "", false, err
38+
}
39+
40+
data, ok := dataMap[key]
41+
if !ok {
42+
return "", false, nil
43+
}
44+
45+
return data, true, nil
46+
}
47+
48+
// GetDataValue return the value of a key stored in "data".
3249
func (cm *ConfigMap) GetDataValue(key string) (string, error) {
3350
// We cant use the "resource.Get" method, because exutil.client will trim the output, removing spaces and newlines that could be important in a configuration.
3451
dataMap, err := cm.GetDataMap()
@@ -44,6 +61,7 @@ func (cm *ConfigMap) GetDataValue(key string) (string, error) {
4461
}
4562

4663
return data, nil
64+
4765
}
4866

4967
// GetDataMap returns the valus in the .data field as a map[string][string]
@@ -61,7 +79,7 @@ func (cm *ConfigMap) GetDataMap() (map[string]string, error) {
6179
return data, nil
6280
}
6381

64-
// GetDataValueOrFail returns the value of a specific key in the .data field and fails the test if any error happens
82+
// GetDataValueOrFail return the value of a key stored in "data" and fails the test if the value cannot be retreived. If the "key" does not exist, it returns an empty string but does not fail
6583
func (cm *ConfigMap) GetDataValueOrFail(key string) string {
6684
value, err := cm.GetDataValue(key)
6785
o.ExpectWithOffset(1, err).NotTo(o.HaveOccurred(),
@@ -71,6 +89,52 @@ func (cm *ConfigMap) GetDataValueOrFail(key string) string {
7189
return value
7290
}
7391

92+
// SetData update the configmap with the given values. Same as "oc set data cm/..."
93+
func (cm *ConfigMap) SetData(arg string, args ...string) error {
94+
params := []string{"data"}
95+
params = append(params, cm.Resource.getCommonParams()...)
96+
params = append(params, arg)
97+
if len(args) > 0 {
98+
params = append(params, args...)
99+
}
100+
101+
return cm.Resource.oc.WithoutNamespace().Run("set").Args(params...).Execute()
102+
}
103+
104+
// RemoveDataKey removes a key from the configmap data values
105+
func (cm *ConfigMap) RemoveDataKey(key string) error {
106+
return cm.Patch("json", `[{"op": "remove", "path": "/data/`+key+`"}]`)
107+
}
108+
109+
// CreateConfigMapWithRandomCert creates a configmap that stores a random CA in it
110+
func CreateConfigMapWithRandomCert(oc *exutil.CLI, cmNamespace, cmName, certKey string) (*ConfigMap, error) {
111+
_, caPath, err := createCA(createTmpDir(), certKey)
112+
if err != nil {
113+
return nil, err
114+
}
115+
116+
err = oc.WithoutNamespace().Run("create").Args("cm", "-n", cmNamespace, cmName, "--from-file", caPath).Execute()
117+
118+
if err != nil {
119+
return nil, err
120+
}
121+
122+
return NewConfigMap(oc, cmNamespace, cmName), nil
123+
}
124+
125+
// GetCloudProviderConfigMap will return the CloudProviderConfigMap or nil if it is not defined in the infrastructure resource
126+
func GetCloudProviderConfigMap(oc *exutil.CLI) *ConfigMap {
127+
infra := NewResource(oc, "infrastructure", "cluster")
128+
cmName := infra.GetOrFail(`{.spec.cloudConfig.name}`)
129+
130+
if cmName == "" {
131+
logger.Infof("CloudProviderConfig ConfigMap is not defined in the infrastructure resource: %s", infra.PrettyString())
132+
return nil
133+
}
134+
135+
return NewConfigMap(oc, "openshift-config", cmName)
136+
}
137+
74138
// GetAll returns a []*ConfigMap list with all existing pinnedimageset sorted by creation timestamp
75139
func (cml *ConfigMapList) GetAll() ([]*ConfigMap, error) {
76140
cml.ResourceList.SortByTimestamp()

test/extended-priv/const.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ const (
6060
// ExtensionsChangeIncWait extra minutes that MCPs will wait per node if we change the extensions in a configuration
6161
ExtensionsChangeIncWait = 5
6262

63+
// ImageRegistryCertificatesDir is the path were the image registry certificates will be stored in a node. Example: /etc/docker/certs.d/mycertname/ca.crt
64+
ImageRegistryCertificatesDir = "/etc/docker/certs.d"
65+
66+
// ImageRegistryCertificatesFileName is the name of the image registry certificates. Example: /etc/docker/certs.d/mycertname/ca.crt
67+
ImageRegistryCertificatesFileName = "ca.crt"
68+
69+
// SecurePort is the tls secured port to serve ignition configs
70+
IgnitionSecurePort = 22623
71+
// InsecurePort is the port to serve ignition configs w/o tls
72+
IgnitionInsecurePort = 22624
73+
6374
// MachineAPINamespace is the MachineAPI namespace
6475
MachineAPINamespace = "openshift-machine-api"
6576

@@ -87,6 +98,8 @@ const (
8798
BusyBoxImage = "quay.io/openshifttest/busybox@sha256:c5439d7db88ab5423999530349d327b04279ad3161d7596d2126dfb5b02bfd1f"
8899
// AlpineImage the multiplatform alpine image stored in openshifttest
89100
AlpineImage = "quay.io/openshifttest/alpine@sha256:dc1536cbff0ba235d4219462aeccd4caceab9def96ae8064257d049166890083"
101+
// TestSSLImage the testssl image stored in openshiftest
102+
TestSSLImage = "quay.io/openshifttest/testssl@sha256:ad6fb8002cb9cfce3ddc8829fd6e7e0d997aeb1faf972650f3e5d7603f90c6ef"
90103

91104
// Constants for NodeDisruptionPolicy
92105
NodeDisruptionPolicyActionNone = "None"
@@ -107,4 +120,13 @@ const (
107120
SkewEnforcementAutomaticMode = "Automatic"
108121
// SkewEnforcementNoneMode indicates boot image skew enforcement is disabled
109122
SkewEnforcementNoneMode = "None"
123+
124+
// MachineConfigServer mcs container name
125+
MachineConfigServer = "machine-config-server"
126+
127+
// TLS Security Version
128+
VersionTLS10 = 0x0301
129+
VersionTLS11 = 0x0302
130+
VersionTLS12 = 0x0303
131+
VersionTLS13 = 0x0304
110132
)
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
package extended
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
7+
b64 "encoding/base64"
8+
9+
exutil "github.com/openshift/machine-config-operator/test/extended-priv/util"
10+
logger "github.com/openshift/machine-config-operator/test/extended-priv/util/logext"
11+
"github.com/tidwall/gjson"
12+
)
13+
14+
// ControllerConfig struct is used to handle ControllerConfig resources in OCP
15+
type ControllerConfig struct {
16+
Resource
17+
}
18+
19+
// CertificateInfo stores the information regarding a given certificate
20+
type CertificateInfo struct {
21+
// subject is the cert subject
22+
Subject string `json:"subject"`
23+
24+
// signer is the cert Issuer
25+
Signer string `json:"signer"`
26+
27+
// Date fields have been temporarily removed by devs: https://github.com/openshift/machine-config-operator/pull/3866
28+
// notBefore is the lower boundary for validity
29+
NotBefore string `json:"notBefore"`
30+
31+
// notAfter is the upper boundary for validity
32+
NotAfter string `json:"notAfter"`
33+
34+
// bundleFile is the larger bundle a cert comes from
35+
BundleFile string `json:"bundleFile"`
36+
}
37+
38+
// NewControllerConfig create a ControllerConfig struct
39+
func NewControllerConfig(oc *exutil.CLI, name string) *ControllerConfig {
40+
return &ControllerConfig{Resource: *NewResource(oc, "ControllerConfig", name)}
41+
}
42+
43+
// GetKubeAPIServerServingCAData return the base64 decoded value of the kubeAPIServerServingCAData bundle stored in the ControllerConfig
44+
func (cc *ControllerConfig) GetKubeAPIServerServingCAData() (string, error) {
45+
b64KubeAPIServerServingData, err := cc.Get(`{.spec.kubeAPIServerServingCAData}`)
46+
if err != nil {
47+
return "", err
48+
}
49+
50+
kubeAPIServerServingCAData, err := b64.StdEncoding.DecodeString(b64KubeAPIServerServingData)
51+
if err != nil {
52+
return "", err
53+
}
54+
return string(kubeAPIServerServingCAData), err
55+
}
56+
57+
// GetRootCAData return the base64 decoded value of the rootCA bundle stored in the ControllerConfig
58+
func (cc *ControllerConfig) GetRootCAData() (string, error) {
59+
b64RootCAData, err := cc.Get(`{.spec.rootCAData}`)
60+
if err != nil {
61+
return "", err
62+
}
63+
64+
rootCAData, err := b64.StdEncoding.DecodeString(b64RootCAData)
65+
if err != nil {
66+
return "", err
67+
}
68+
return string(rootCAData), err
69+
}
70+
71+
// GetImageRegistryBundleData returns a map[string]string containing the filenames and values of the image registry bundle data
72+
func (cc *ControllerConfig) GetImageRegistryBundleData() (map[string]string, error) {
73+
return cc.GetImageRegistryBundle("imageRegistryBundleData")
74+
}
75+
76+
// GetImageRegistryBundleUserData returns a map[string]string containing the filenames and values of the image registry bundle user data
77+
func (cc *ControllerConfig) GetImageRegistryBundleUserData() (map[string]string, error) {
78+
return cc.GetImageRegistryBundle("imageRegistryBundleUserData")
79+
}
80+
81+
// GetImageRegistryBundle returns a map[string]string containing the filenames and values of the image registry certificates in a Bundle field
82+
func (cc *ControllerConfig) GetImageRegistryBundle(bundleField string) (map[string]string, error) {
83+
certs := map[string]string{}
84+
85+
bundleData, err := cc.Get(`{.spec.` + bundleField + `}`)
86+
if err != nil {
87+
return nil, err
88+
}
89+
90+
parsedBundleData := gjson.Parse(bundleData)
91+
92+
var b64Err error
93+
parsedBundleData.ForEach(func(_, item gjson.Result) bool {
94+
file := item.Get("file").String()
95+
data64 := item.Get("data").String()
96+
97+
data, b64Err := b64.StdEncoding.DecodeString(data64)
98+
if err != nil {
99+
logger.Infof("Error decoding data for image registry bundle file %s: %s", file, b64Err)
100+
return false // stop iterating
101+
}
102+
103+
certs[file] = string(data)
104+
return true // keep iterating
105+
})
106+
if b64Err != nil {
107+
return nil, b64Err
108+
}
109+
110+
return certs, nil
111+
}
112+
113+
// GetImageRegistryBundleByFileName returns the image registry bundle searching by bundle filename
114+
func (cc *ControllerConfig) GetImageRegistryBundleDataByFileName(fileName string) (string, error) {
115+
certs, err := cc.GetImageRegistryBundleData()
116+
if err != nil {
117+
return "", err
118+
}
119+
120+
data, ok := certs[fileName]
121+
if !ok {
122+
return "", fmt.Errorf("There is no image registry bundle with file name %s", fileName)
123+
}
124+
125+
return data, nil
126+
}
127+
128+
// GetImageRegistryUserBundleByFileName returns the image registry bundle searching by bundle filename
129+
func (cc *ControllerConfig) GetImageRegistryBundleUserDataByFileName(fileName string) (string, error) {
130+
certs, err := cc.GetImageRegistryBundleUserData()
131+
if err != nil {
132+
return "", err
133+
}
134+
135+
data, ok := certs[fileName]
136+
if !ok {
137+
return "", fmt.Errorf("There is no image registry bundle with file name %s", fileName)
138+
}
139+
140+
return data, nil
141+
}
142+
143+
// Returns a list of CertificateInfo structs with the information of all the certificates tracked by ControllerConfig
144+
func (cc *ControllerConfig) GetCertificatesInfo() ([]CertificateInfo, error) {
145+
certsInfoString := cc.GetOrFail(`{.status.controllerCertificates}`)
146+
147+
logger.Debugf("CERTIFICATES: %s", certsInfoString)
148+
149+
var certsInfo []CertificateInfo
150+
151+
jsonerr := json.Unmarshal([]byte(certsInfoString), &certsInfo)
152+
153+
if jsonerr != nil {
154+
return nil, jsonerr
155+
}
156+
157+
return certsInfo, nil
158+
}
159+
160+
func (cc *ControllerConfig) GetCertificatesInfoByBundleFileName(bundleFile string) ([]CertificateInfo, error) {
161+
162+
var certsInfo []CertificateInfo
163+
164+
allCertsInfo, err := cc.GetCertificatesInfo()
165+
if err != nil {
166+
return nil, err
167+
}
168+
169+
for _, ciLoop := range allCertsInfo {
170+
ci := ciLoop
171+
if ci.BundleFile == bundleFile {
172+
certsInfo = append(certsInfo, ci)
173+
}
174+
}
175+
176+
return certsInfo, nil
177+
}

0 commit comments

Comments
 (0)