Skip to content

Commit

Permalink
[FeatureGate/KMSEncryptionProvider] APIServer config for AWS KMS
Browse files Browse the repository at this point in the history
Signed-off-by: Swarup Ghosh <[email protected]>
  • Loading branch information
swghosh committed Dec 2, 2024
1 parent b598199 commit a0a5ff2
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
apiVersion: apiextensions.k8s.io/v1 # Hack because controller-gen complains if we don't have this
name: "APIServer"
crdName: apiservers.config.openshift.io
featureGates:
- KMSEncryptionProvider
tests:
onCreate:
- name: Should be able to create encrypt with KMS for AWS with valid values
initial: |
apiVersion: config.openshift.io/v1
kind: APIServer
spec:
encryption:
type: KMS
kms:
type: AWS
aws:
keyARN: arn:aws:kms:us-east-1:101010101010:key/9a512e29-0d9c-4cf5-8174-fc1a5b22cd6a
region: us-east-1
expected: |
apiVersion: config.openshift.io/v1
kind: APIServer
spec:
audit:
profile: Default
encryption:
type: KMS
kms:
type: AWS
aws:
keyARN: arn:aws:kms:us-east-1:101010101010:key/9a512e29-0d9c-4cf5-8174-fc1a5b22cd6a
region: us-east-1
- name: Should be able to create encrypt with KMS for AWS without region
initial: |
apiVersion: config.openshift.io/v1
kind: APIServer
spec:
encryption:
type: KMS
kms:
type: AWS
aws:
keyARN: arn:aws:kms:us-east-1:101010101010:key/9a512e29-0d9c-4cf5-8174-fc1a5b22cd6a
expected: |
apiVersion: config.openshift.io/v1
kind: APIServer
spec:
audit:
profile: Default
encryption:
type: KMS
kms:
type: AWS
aws:
keyARN: arn:aws:kms:us-east-1:101010101010:key/9a512e29-0d9c-4cf5-8174-fc1a5b22cd6a
- name: Should not allow kms config with encrypt aescbc
initial: |
apiVersion: config.openshift.io/v1
kind: APIServer
spec:
encryption:
type: aescbc
kms:
type: AWS
aws:
keyARN: arn:aws:kms:us-east-1:101010101010:key/9a512e29-0d9c-4cf5-8174-fc1a5b22cd6a
expectedError: "kms config is required when encryption type is KMS, and forbidden otherwise"
- name: Should fail to create with an empty KMS config
initial: |
apiVersion: config.openshift.io/v1
kind: APIServer
spec:
encryption:
type: KMS
kms: {}
expectedError: "spec.encryption.kms.type: Required value"
- name: Should fail to create with kms type AWS but without aws config
initial: |
apiVersion: config.openshift.io/v1
kind: APIServer
spec:
encryption:
type: KMS
kms:
type: AWS
expectedError: "aws config is required when kms provider type is AWS, and forbidden otherwise"
- name: Should fail to create AWS KMS without a keyARN
initial: |
apiVersion: config.openshift.io/v1
kind: APIServer
spec:
encryption:
type: KMS
kms:
type: AWS
aws:
region: us-east-1
expectedError: "spec.encryption.kms.aws.keyARN: Required value"
- name: Should fail to create AWS KMS with invalid keyARN format
initial: |
apiVersion: config.openshift.io/v1
kind: APIServer
spec:
encryption:
type: KMS
kms:
type: AWS
aws:
keyARN: not-a-kms-arn
region: us-east-1
expectedError: "keyARN must follow the format `arn:aws:kms:<region>:<account_id>:key/<key_id>`. The account ID must be a 12 digit number and the region and key ID should consist only of lowercase hexadecimal characters and hyphens (-)."
- name: Should fail to create AWS KMS with empty region
initial: |
apiVersion: config.openshift.io/v1
kind: APIServer
spec:
encryption:
type: KMS
kms:
type: AWS
aws:
keyARN: arn:aws:kms:us-east-1:101010101010:key/9a512e29-0d9c-4cf5-8174-fc1a5b22cd6a
region: ""
expectedError: "spec.encryption.kms.aws.region in body should be at least 1 chars long"
- name: Should fail to create AWS KMS with invalid region format
initial: |
apiVersion: config.openshift.io/v1
kind: APIServer
spec:
encryption:
type: KMS
kms:
type: AWS
aws:
keyARN: arn:aws:kms:us-east-1:101010101010:key/9a512e29-0d9c-4cf5-8174-fc1a5b22cd6a
region: "INVALID-REGION"
expectedError: "region must be a valid AWS region, consisting of lowercase characters, digits and hyphens (-) only."
27 changes: 26 additions & 1 deletion config/v1/types_apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type APIServerSpec struct {
// server from JavaScript applications.
// The values are regular expressions that correspond to the Golang regular expression language.
// +optional
// +listType=atomic
AdditionalCORSAllowedOrigins []string `json:"additionalCORSAllowedOrigins,omitempty"`
// encryption allows the configuration of encryption of resources at the datastore layer.
// +optional
Expand Down Expand Up @@ -156,6 +157,7 @@ type APIServerServingCerts struct {
// If no named certificates are provided, or no named certificates match the server name as understood by a client,
// the defaultServingCertificate will be used.
// +optional
// +listType=atomic
NamedCertificates []APIServerNamedServingCert `json:"namedCertificates,omitempty"`
}

Expand All @@ -165,6 +167,7 @@ type APIServerNamedServingCert struct {
// serve secure traffic. If no names are provided, the implicit names will be extracted from the certificates.
// Exact names trump over wildcard names. Explicit names defined here trump over extracted implicit names.
// +optional
// +listType=atomic
Names []string `json:"names,omitempty"`
// servingCertificate references a kubernetes.io/tls type secret containing the TLS cert info for serving secure traffic.
// The secret must exist in the openshift-config namespace and contain the following required fields:
Expand All @@ -173,6 +176,9 @@ type APIServerNamedServingCert struct {
ServingCertificate SecretNameReference `json:"servingCertificate"`
}

// APIServerEncryption is used to encrypt sensitive resources on the cluster.
// +openshift:validation:FeatureGateAwareXValidation:featureGate=KMSEncryptionProvider,rule="has(self.type) && self.type == 'KMS' ? has(self.kms) : !has(self.kms)",message="kms config is required when encryption type is KMS, and forbidden otherwise"
// +union
type APIServerEncryption struct {
// type defines what encryption type should be used to encrypt resources at the datastore layer.
// When this field is unset (i.e. when it is set to the empty string), identity is implied.
Expand All @@ -191,9 +197,23 @@ type APIServerEncryption struct {
// +unionDiscriminator
// +optional
Type EncryptionType `json:"type,omitempty"`

// kms defines the configuration for the external KMS instance that manages the encryption keys,
// when KMS encryption is enabled sensitive resources will be encrypted using keys managed by an
// externally configured KMS instance.
//
// The Key Management Service (KMS) instance provides symmetric encryption and is responsible for
// managing the lifecyle of the encryption keys outside of the control plane.
// This allows integration with an external provider to manage the data encryption keys securely.
//
// +openshift:enable:FeatureGate=KMSEncryptionProvider
// +unionMember
// +optional
KMS *KMSConfig `json:"kms,omitempty"`
}

// +kubebuilder:validation:Enum="";identity;aescbc;aesgcm
// +openshift:validation:FeatureGateAwareEnum:featureGate="",enum="";identity;aescbc;aesgcm
// +openshift:validation:FeatureGateAwareEnum:featureGate=KMSEncryptionProvider,enum="";identity;aescbc;aesgcm;KMS
type EncryptionType string

const (
Expand All @@ -208,6 +228,11 @@ const (
// aesgcm refers to a type where AES-GCM with random nonce and a 32-byte key
// is used to perform encryption at the datastore layer.
EncryptionTypeAESGCM EncryptionType = "aesgcm"

// kms refers to a type of encryption where the encryption keys are managed
// outside the control plane in a Key Management Service instance,
// encryption is still performed at the datastore layer.
EncryptionTypeKMS EncryptionType = "KMS"
)

type APIServerStatus struct {
Expand Down
54 changes: 54 additions & 0 deletions config/v1/types_kmsencryption.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package v1

// KMSConfig defines the configuration for the KMS instance
// that will be used with KMSEncryptionProvider encryption
// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'AWS' ? has(self.aws) : !has(self.aws)",message="aws config is required when kms provider type is AWS, and forbidden otherwise"
// +union
type KMSConfig struct {
// type defines the kind of platform for the KMS provider.
// Available provider types are AWS only.
//
// +unionDiscriminator
// +kubebuilder:validation:Required
Type KMSProviderType `json:"type"`

// aws defines the key config for using an AWS KMS instance
// for the encryption. The AWS KMS instance is managed
// by the user outside the purview of the control plane.
//
// +unionMember
// +optional
AWS *AWSKMSConfig `json:"aws,omitempty"`
}

// AWSKMSConfig defines the KMS config specific to AWS KMS provider
type AWSKMSConfig struct {
// keyARN specifies the Amazon Resource Name (ARN) of the AWS KMS key used for encryption.
// The value must adhere to the format `arn:aws:kms:<region>:<account_id>:key/<key_id>`, where:
// - `<region>` is the AWS region consisting of lowercase letters and hyphens followed by a number.
// - `<account_id>` is a 12-digit numeric identifier for the AWS account.
// - `<key_id>` is a unique identifier for the KMS key, consisting of lowercase hexadecimal characters and hyphens.
//
// +kubebuilder:validation:Required
// +kubebuilder:validation:MaxLength=128
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:XValidation:rule="self.matches('^arn:aws:kms:[a-z0-9-]+:[0-9]{12}:key/[a-f0-9-]+$')",message="keyARN must follow the format `arn:aws:kms:<region>:<account_id>:key/<key_id>`. The account ID must be a 12 digit number and the region and key ID should consist only of lowercase hexadecimal characters and hyphens (-)."
KeyARN string `json:"keyARN"`
// region specifies the AWS region where the KMS instance exists, and follows the format
// `<region-prefix>-<region-name>-<number>`, e.g.: `us-east-1`.
// Only lowercase letters and hyphens followed by numbers are allowed.
//
// +kubebuilder:validation:MaxLength=64
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:XValidation:rule="self.matches('^[a-z0-9]+(-[a-z0-9]+)*$')",message="region must be a valid AWS region, consisting of lowercase characters, digits and hyphens (-) only."
Region string `json:"region"`
}

// KMSProviderType is a specific supported KMS provider
// +kubebuilder:validation:Enum=AWS
type KMSProviderType string

const (
// AWSKMSProvider represents a supported KMS provider for use with AWS KMS
AWSKMSProvider KMSProviderType = "AWS"
)

0 comments on commit a0a5ff2

Please sign in to comment.