Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add ability to configure ShieldedInstanceConfig in GCPMachinePool Specification. #23

Merged
merged 5 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions cloud/scope/machinepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,10 +405,36 @@ func (m *MachinePoolScope) InstanceGroupTemplateBuilder(bootstrapData string) *c
instanceTemplate.Properties.ServiceAccounts = append(instanceTemplate.Properties.ServiceAccounts, m.InstanceServiceAccountsSpec())
instanceTemplate.Properties.NetworkInterfaces = append(instanceTemplate.Properties.NetworkInterfaces, m.InstanceNetworkInterfaceSpec())
instanceTemplate.Properties.Metadata.Items = append(instanceTemplate.Properties.Metadata.Items, m.InstanceAdditionalMetadataSpec()...)
instanceTemplate.Properties.ShieldedInstanceConfig = m.GetShieldedInstanceConfigSpec()

return instanceTemplate
}

// GetShieldedInstanceConfigSpec returns the shielded config spec for the instance
// As of now will only build the configuration for using
// - Integrity Monitoring - enabled by default
// - Secure Boot - disabled by default
// - vTPM - enabled by default.
func (m *MachinePoolScope) GetShieldedInstanceConfigSpec() *compute.ShieldedInstanceConfig {
shieldedInstanceConfig := &compute.ShieldedInstanceConfig{
EnableSecureBoot: false,
EnableVtpm: true,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these the defaults that GCP applies? Im afraid to make assumptions on bool values for upstream workers.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the InstanceSpec method for machine object also does similarly for reference https://github.com/newrelic-forks/cluster-api-provider-gcp/blob/main/cloud/scope/machine.go#L404-L410

EnableIntegrityMonitoring: true,
}
if m.GCPMachinePool.Spec.ShieldedInstanceConfig != nil {
if m.GCPMachinePool.Spec.ShieldedInstanceConfig.SecureBoot == infrav1exp.SecureBootPolicyEnabled {
shieldedInstanceConfig.EnableSecureBoot = true
}
if m.GCPMachinePool.Spec.ShieldedInstanceConfig.VirtualizedTrustedPlatformModule == infrav1exp.VirtualizedTrustedPlatformModulePolicyDisabled {
shieldedInstanceConfig.EnableVtpm = false
}
if m.GCPMachinePool.Spec.ShieldedInstanceConfig.IntegrityMonitoring == infrav1exp.IntegrityMonitoringPolicyDisabled {
shieldedInstanceConfig.EnableIntegrityMonitoring = false
}
}
return shieldedInstanceConfig
}

// InstanceNetworkInterfaceSpec returns the network interface spec for the instance.
func (m *MachinePoolScope) InstanceNetworkInterfaceSpec() *compute.NetworkInterface {
networkInterface := &compute.NetworkInterface{
Expand Down
66 changes: 60 additions & 6 deletions cloud/scope/machinepool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
infrav1 "sigs.k8s.io/cluster-api-provider-gcp/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-gcp/cloud"
"sigs.k8s.io/cluster-api-provider-gcp/cloud/scope"
"sigs.k8s.io/cluster-api-provider-gcp/exp/api/v1beta1"
infrav1exp "sigs.k8s.io/cluster-api-provider-gcp/exp/api/v1beta1"
"sigs.k8s.io/cluster-api-provider-gcp/util/processors"
clusterv1exp "sigs.k8s.io/cluster-api/exp/api/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
Expand All @@ -21,11 +21,12 @@ import (
var _ = Describe("GCPManagedMachinePool Scope", func() {
var TestMachinePoolScope *scope.MachinePoolScope
var getter cloud.ClusterGetter
var mpscopeparams scope.MachinePoolScopeParams
var t *testing.T

BeforeEach(func() {
// Register the MachinePool, GCPMachinePool and GCPMachinePoolList in a schema.
schema, err := infrav1.SchemeBuilder.Register(&clusterv1exp.MachinePool{}, &v1beta1.GCPMachinePool{}, &v1beta1.GCPMachinePoolList{}).Build()
schema, err := infrav1.SchemeBuilder.Register(&clusterv1exp.MachinePool{}, &infrav1exp.GCPMachinePool{}, &infrav1exp.GCPMachinePoolList{}).Build()
// Make sure no errors were triggered.
assert.Nil(t, err)

Expand All @@ -35,19 +36,19 @@ var _ = Describe("GCPManagedMachinePool Scope", func() {
testClient := fake.NewClientBuilder().WithScheme(schema).Build()

// Create the machinepool scope
params := scope.MachinePoolScopeParams{
mpscopeparams = scope.MachinePoolScopeParams{
Client: testClient,
ClusterGetter: getter,
MachinePool: &clusterv1exp.MachinePool{
ObjectMeta: metav1.ObjectMeta{},
Spec: clusterv1exp.MachinePoolSpec{},
},
GCPMachinePool: &v1beta1.GCPMachinePool{
GCPMachinePool: &infrav1exp.GCPMachinePool{
ObjectMeta: metav1.ObjectMeta{},
Spec: v1beta1.GCPMachinePoolSpec{},
Spec: infrav1exp.GCPMachinePoolSpec{},
},
}
TestMachinePoolScope, _ = scope.NewMachinePoolScope(params)
TestMachinePoolScope, _ = scope.NewMachinePoolScope(mpscopeparams)

// Make sure the machinepool scope is created correctly.
assert.Nil(t, err)
Expand All @@ -69,4 +70,57 @@ var _ = Describe("GCPManagedMachinePool Scope", func() {
})
})
})

Describe("GCPMachinePool Spec has no ShieldedInstanceConfig passed", func() {
It("should have Integrity Monitoring set to true", func() {
shieldedVMConfig := TestMachinePoolScope.GetShieldedInstanceConfigSpec()
Expect(shieldedVMConfig.EnableIntegrityMonitoring).To(BeTrue())
})
It("should have Secure Boot set to false", func() {
shieldedVMConfig := TestMachinePoolScope.GetShieldedInstanceConfigSpec()
Expect(shieldedVMConfig.EnableSecureBoot).To(BeFalse())
})
It("should have vTPM set to true", func() {
shieldedVMConfig := TestMachinePoolScope.GetShieldedInstanceConfigSpec()
Expect(shieldedVMConfig.EnableVtpm).To(BeTrue())
})
})

Describe("GCPMachinePool Spec has ShieldedInstanceConfig passed", func() {
Context("Secure Boot is enabled in gcpmacninepool.spec", func() {
It("should have secure boot set to true", func() {
mpscopeparams.GCPMachinePool.Spec = infrav1exp.GCPMachinePoolSpec{
ShieldedInstanceConfig: &infrav1exp.GCPShieldedInstanceConfig{
SecureBoot: infrav1exp.SecureBootPolicyEnabled,
},
}
shieldedVMConfig := TestMachinePoolScope.GetShieldedInstanceConfigSpec()
Expect(shieldedVMConfig.EnableIntegrityMonitoring).To(BeTrue())
})
})

Context("vTPM is disabled in gcpmacninepool.spec", func() {
It("should have secure boot set to false", func() {
mpscopeparams.GCPMachinePool.Spec = infrav1exp.GCPMachinePoolSpec{
ShieldedInstanceConfig: &infrav1exp.GCPShieldedInstanceConfig{
VirtualizedTrustedPlatformModule: infrav1exp.VirtualizedTrustedPlatformModulePolicyDisabled,
},
}
shieldedVMConfig := TestMachinePoolScope.GetShieldedInstanceConfigSpec()
Expect(shieldedVMConfig.EnableVtpm).To(BeFalse())
})
})

Context("Integrity Monitoring is disabled in gcpmacninepool.spec", func() {
It("should have Integrity Monitoring set to false", func() {
mpscopeparams.GCPMachinePool.Spec = infrav1exp.GCPMachinePoolSpec{
ShieldedInstanceConfig: &infrav1exp.GCPShieldedInstanceConfig{
IntegrityMonitoring: infrav1exp.IntegrityMonitoringPolicyDisabled,
},
}
shieldedVMConfig := TestMachinePoolScope.GetShieldedInstanceConfigSpec()
Expect(shieldedVMConfig.EnableIntegrityMonitoring).To(BeFalse())
})
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,46 @@ spec:
type: string
type: array
type: object
shieldedInstanceConfig:
description: ShieldedInstanceConfig is the Shielded VM configuration
for this machine
properties:
integrityMonitoring:
description: IntegrityMonitoring determines whether the instance
should have integrity monitoring that verify the runtime boot
integrity. Compares the most recent boot measurements to the
integrity policy baseline and return a pair of pass/fail results
depending on whether they match or not. If omitted, the platform
chooses a default, which is subject to change over time, currently
that default is Enabled.
enum:
- Enabled
- Disabled
type: string
secureBoot:
description: SecureBoot Defines whether the instance should have
secure boot enabled. Secure Boot verify the digital signature
of all boot components, and halting the boot process if signature
verification fails. If omitted, the platform chooses a default,
which is subject to change over time, currently that default
is Disabled.
enum:
- Enabled
- Disabled
type: string
virtualizedTrustedPlatformModule:
description: VirtualizedTrustedPlatformModule enable virtualized
trusted platform module measurements to create a known good
boot integrity policy baseline. The integrity policy baseline
is used for comparison with measurements from subsequent VM
boots to determine if anything has changed. If omitted, the
platform chooses a default, which is subject to change over
time, currently that default is Enabled.
enum:
- Enabled
- Disabled
type: string
type: object
strategy:
default:
rollingUpdate:
Expand Down
60 changes: 60 additions & 0 deletions exp/api/v1beta1/gcpmachinepool_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ type GCPMachinePoolSpec struct {
// +kubebuilder:default={type: "RollingUpdate", rollingUpdate: {maxSurge: 1, maxUnavailable: 0, deletePolicy: Oldest}}
Strategy GCPMachinePoolDeploymentStrategy `json:"strategy,omitempty"`

// ShieldedInstanceConfig is the Shielded VM configuration for this machine
// +optional
ShieldedInstanceConfig *GCPShieldedInstanceConfig `json:"shieldedInstanceConfig,omitempty"`

// NodeDrainTimeout is the total amount of time that the controller will spend on draining a node.
// The default value is 0, meaning that the node can be drained without any time limitations.
// NOTE: NodeDrainTimeout is different from `kubectl drain --timeout`
Expand All @@ -185,6 +189,62 @@ type GCPMachinePoolSpec struct {
Zone string `json:"zone"`
}

// SecureBootPolicy represents the secure boot configuration for the GCP machine.
type SecureBootPolicy string

const (
// SecureBootPolicyEnabled enables the secure boot configuration for the GCP machine.
SecureBootPolicyEnabled SecureBootPolicy = "Enabled"
// SecureBootPolicyDisabled disables the secure boot configuration for the GCP machine.
SecureBootPolicyDisabled SecureBootPolicy = "Disabled"
)

// VirtualizedTrustedPlatformModulePolicy represents the virtualized trusted platform module configuration for the GCP machine.
type VirtualizedTrustedPlatformModulePolicy string

const (
// VirtualizedTrustedPlatformModulePolicyEnabled enables the virtualized trusted platform module configuration for the GCP machine.
VirtualizedTrustedPlatformModulePolicyEnabled VirtualizedTrustedPlatformModulePolicy = "Enabled"
// VirtualizedTrustedPlatformModulePolicyDisabled disables the virtualized trusted platform module configuration for the GCP machine.
VirtualizedTrustedPlatformModulePolicyDisabled VirtualizedTrustedPlatformModulePolicy = "Disabled"
)

// IntegrityMonitoringPolicy represents the integrity monitoring configuration for the GCP machine.
type IntegrityMonitoringPolicy string

const (
// IntegrityMonitoringPolicyEnabled enables integrity monitoring for the GCP machine.
IntegrityMonitoringPolicyEnabled IntegrityMonitoringPolicy = "Enabled"
// IntegrityMonitoringPolicyDisabled disables integrity monitoring for the GCP machine.
IntegrityMonitoringPolicyDisabled IntegrityMonitoringPolicy = "Disabled"
)

// GCPShieldedInstanceConfig describes the shielded VM configuration of the instance on GCP.
// Shielded VM configuration allow users to enable and disable Secure Boot, vTPM, and Integrity Monitoring.
type GCPShieldedInstanceConfig struct {
// SecureBoot Defines whether the instance should have secure boot enabled.
// Secure Boot verify the digital signature of all boot components, and halting the boot process if signature verification fails.
// If omitted, the platform chooses a default, which is subject to change over time, currently that default is Disabled.
// +kubebuilder:validation:Enum=Enabled;Disabled
//+optional
SecureBoot SecureBootPolicy `json:"secureBoot,omitempty"`

// VirtualizedTrustedPlatformModule enable virtualized trusted platform module measurements to create a known good boot integrity policy baseline.
// The integrity policy baseline is used for comparison with measurements from subsequent VM boots to determine if anything has changed.
// If omitted, the platform chooses a default, which is subject to change over time, currently that default is Enabled.
// +kubebuilder:validation:Enum=Enabled;Disabled
// +optional
VirtualizedTrustedPlatformModule VirtualizedTrustedPlatformModulePolicy `json:"virtualizedTrustedPlatformModule,omitempty"`

// IntegrityMonitoring determines whether the instance should have integrity monitoring that verify the runtime boot integrity.
// Compares the most recent boot measurements to the integrity policy baseline and return
// a pair of pass/fail results depending on whether they match or not.
// If omitted, the platform chooses a default, which is subject to change over time, currently that default is Enabled.
// +kubebuilder:validation:Enum=Enabled;Disabled
// +optional
IntegrityMonitoring IntegrityMonitoringPolicy `json:"integrityMonitoring,omitempty"`
}

// GCPMachinePoolDeploymentStrategyType is the type of deployment strategy employed to rollout a new version of the GCPMachinePool.
type GCPMachinePoolDeploymentStrategyType string

Expand Down
20 changes: 20 additions & 0 deletions exp/api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion test/e2e/data/cni/calico/calico.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ spec:
numAllowedLocalASNumbers:
description: Maximum number of local AS numbers that are allowed in
the AS path for received routes. This removes BGP loop prevention
and should only be used if absolutely necesssary.
and should only be used if absolutely necessary.
format: int32
type: integer
password:
Expand Down
Loading