diff --git a/apis/v1alpha1/ack-generate-metadata.yaml b/apis/v1alpha1/ack-generate-metadata.yaml index 3cceb15..83030d5 100755 --- a/apis/v1alpha1/ack-generate-metadata.yaml +++ b/apis/v1alpha1/ack-generate-metadata.yaml @@ -1,8 +1,8 @@ ack_generate_info: - build_date: "2023-03-23T17:58:11Z" - build_hash: fa24753ea8b657d8815ae3eac7accd0958f5f9fb - go_version: go1.19.1 - version: v0.25.0 + build_date: "2023-05-15T23:04:21Z" + build_hash: 8f3ba427974fd6e769926778d54834eaee3b81a3 + go_version: go1.19 + version: v0.26.1 api_directory_checksum: 70eb6bda460cfa4eda159f3e887696468dabf7a2 api_version: v1alpha1 aws_sdk_go_version: v1.44.93 diff --git a/cmd/controller/main.go b/cmd/controller/main.go index 9347bcb..a83bfbc 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -27,6 +27,7 @@ import ( svcsdk "github.com/aws/aws-sdk-go/service/kms" flag "github.com/spf13/pflag" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrlrt "sigs.k8s.io/controller-runtime" ctrlrtmetrics "sigs.k8s.io/controller-runtime/pkg/metrics" @@ -62,7 +63,13 @@ func main() { flag.Parse() ackCfg.SetupLogger() - if err := ackCfg.Validate(); err != nil { + managerFactories := svcresource.GetManagerFactories() + resourceGVKs := make([]schema.GroupVersionKind, 0, len(managerFactories)) + for _, mf := range managerFactories { + resourceGVKs = append(resourceGVKs, mf.ResourceDescriptor().GroupVersionKind()) + } + + if err := ackCfg.Validate(ackcfg.WithGVKs(resourceGVKs)); err != nil { setupLog.Error( err, "Unable to create controller manager", "aws.service", awsServiceAlias, diff --git a/config/controller/deployment.yaml b/config/controller/deployment.yaml index 5bc159d..0625b82 100644 --- a/config/controller/deployment.yaml +++ b/config/controller/deployment.yaml @@ -73,6 +73,9 @@ spec: capabilities: drop: - ALL + securityContext: + seccompProfile: + type: RuntimeDefault terminationGracePeriodSeconds: 10 serviceAccountName: ack-kms-controller hostIPC: false diff --git a/config/controller/kustomization.yaml b/config/controller/kustomization.yaml index cf3ac1c..4d1dcd5 100644 --- a/config/controller/kustomization.yaml +++ b/config/controller/kustomization.yaml @@ -6,4 +6,4 @@ kind: Kustomization images: - name: controller newName: public.ecr.aws/aws-controllers-k8s/kms-controller - newTag: v1.0.4 + newTag: 1.0.5 diff --git a/go.mod b/go.mod index 4bc6c1f..faec9ad 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/aws-controllers-k8s/kms-controller go 1.19 require ( - github.com/aws-controllers-k8s/runtime v0.25.0 + github.com/aws-controllers-k8s/runtime v0.26.0 github.com/aws/aws-sdk-go v1.44.93 github.com/go-logr/logr v1.2.3 github.com/spf13/pflag v1.0.5 diff --git a/go.sum b/go.sum index 5a38194..79ed024 100644 --- a/go.sum +++ b/go.sum @@ -38,8 +38,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/aws-controllers-k8s/runtime v0.25.0 h1:6SYa8qmbw+Yil5/LodF7LmIGxBhpjz4QEIvNjpeRuoc= -github.com/aws-controllers-k8s/runtime v0.25.0/go.mod h1:jizDzKikL09cueIuA9ZxoZ+4pfn5U7oKW5s/ZAqOA6E= +github.com/aws-controllers-k8s/runtime v0.26.0 h1:XKqygFzHSBtM74Ov9IroZbyCVeYei9Eskp4aKbJ2SFw= +github.com/aws-controllers-k8s/runtime v0.26.0/go.mod h1:jizDzKikL09cueIuA9ZxoZ+4pfn5U7oKW5s/ZAqOA6E= github.com/aws/aws-sdk-go v1.44.93 h1:hAgd9fuaptBatSft27/5eBMdcA8+cIMqo96/tZ6rKl8= github.com/aws/aws-sdk-go v1.44.93/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= diff --git a/helm/Chart.yaml b/helm/Chart.yaml index 0abd9bb..74a1cec 100644 --- a/helm/Chart.yaml +++ b/helm/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v1 name: kms-chart description: A Helm chart for the ACK service controller for AWS Key Management Service (KMS) -version: v1.0.4 -appVersion: v1.0.4 +version: 1.0.5 +appVersion: 1.0.5 home: https://github.com/aws-controllers-k8s/kms-controller icon: https://raw.githubusercontent.com/aws/eks-charts/master/docs/logo/aws.png sources: diff --git a/helm/templates/NOTES.txt b/helm/templates/NOTES.txt index 46c520a..f3f331d 100644 --- a/helm/templates/NOTES.txt +++ b/helm/templates/NOTES.txt @@ -1,5 +1,5 @@ {{ .Chart.Name }} has been installed. -This chart deploys "public.ecr.aws/aws-controllers-k8s/kms-controller:v1.0.4". +This chart deploys "public.ecr.aws/aws-controllers-k8s/kms-controller:1.0.5". Check its status by running: kubectl --namespace {{ .Release.Namespace }} get pods -l "app.kubernetes.io/instance={{ .Release.Name }}" diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl index 973704c..391d5de 100644 --- a/helm/templates/_helpers.tpl +++ b/helm/templates/_helpers.tpl @@ -33,7 +33,7 @@ If release name contains chart name it will be used as a full name. {{- define "watch-namespace" -}} {{- if eq .Values.installScope "namespace" -}} -{{- .Release.Namespace -}} +{{ .Values.watchNamespace | default .Release.Namespace }} {{- end -}} {{- end -}} diff --git a/helm/templates/deployment.yaml b/helm/templates/deployment.yaml index b3c0ede..7504a61 100644 --- a/helm/templates/deployment.yaml +++ b/helm/templates/deployment.yaml @@ -116,6 +116,9 @@ spec: capabilities: drop: - ALL + securityContext: + seccompProfile: + type: RuntimeDefault terminationGracePeriodSeconds: 10 nodeSelector: {{ toYaml .Values.deployment.nodeSelector | nindent 8 }} {{ if .Values.deployment.tolerations -}} diff --git a/helm/values.schema.json b/helm/values.schema.json index d5a8d35..79fd18c 100644 --- a/helm/values.schema.json +++ b/helm/values.schema.json @@ -196,6 +196,9 @@ "type": "string", "enum": ["cluster", "namespace"] }, + "watchNamespace": { + "type": "string" + }, "resourceTags": { "type": "array", "items": { diff --git a/helm/values.yaml b/helm/values.yaml index 2e5a861..20e0759 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -4,7 +4,7 @@ image: repository: public.ecr.aws/aws-controllers-k8s/kms-controller - tag: v1.0.4 + tag: 1.0.5 pullPolicy: IfNotPresent pullSecrets: [] @@ -31,7 +31,7 @@ deployment: # If "installScope: cluster" then these labels will be applied to ClusterRole role: - labels: {} + labels: {} metrics: service: @@ -72,6 +72,10 @@ log: # cluster wide. installScope: cluster +# Set the value of the "namespace" to be watched by the controller +# This value is only used when the `installScope` is set to "namespace". If left empty, the default value is the release namespace for the chart. +watchNamespace: "" + resourceTags: # Configures the ACK service controller to always set key/value pairs tags on # resources that it manages. diff --git a/pkg/resource/alias/references.go b/pkg/resource/alias/references.go index 29fd642..5e89323 100644 --- a/pkg/resource/alias/references.go +++ b/pkg/resource/alias/references.go @@ -24,46 +24,56 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" - ackcondition "github.com/aws-controllers-k8s/runtime/pkg/condition" ackerr "github.com/aws-controllers-k8s/runtime/pkg/errors" acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" svcapitypes "github.com/aws-controllers-k8s/kms-controller/apis/v1alpha1" ) +// ClearResolvedReferences removes any reference values that were made +// concrete in the spec. It returns a copy of the input AWSResource which +// contains the original *Ref values, but none of their respective concrete +// values. +func (rm *resourceManager) ClearResolvedReferences(res acktypes.AWSResource) acktypes.AWSResource { + ko := rm.concreteResource(res).ko.DeepCopy() + + if ko.Spec.TargetKeyRef != nil { + ko.Spec.TargetKeyID = nil + } + + return &resource{ko} +} + // ResolveReferences finds if there are any Reference field(s) present -// inside AWSResource passed in the parameter and attempts to resolve -// those reference field(s) into target field(s). -// It returns an AWSResource with resolved reference(s), and an error if the -// passed AWSResource's reference field(s) cannot be resolved. -// This method also adds/updates the ConditionTypeReferencesResolved for the -// AWSResource. +// inside AWSResource passed in the parameter and attempts to resolve those +// reference field(s) into their respective target field(s). It returns a +// copy of the input AWSResource with resolved reference(s), a boolean which +// is set to true if the resource contains any references (regardless of if +// they are resolved successfully) and an error if the passed AWSResource's +// reference field(s) could not be resolved. func (rm *resourceManager) ResolveReferences( ctx context.Context, apiReader client.Reader, res acktypes.AWSResource, -) (acktypes.AWSResource, error) { +) (acktypes.AWSResource, bool, error) { namespace := res.MetaObject().GetNamespace() - ko := rm.concreteResource(res).ko.DeepCopy() + ko := rm.concreteResource(res).ko + + resourceHasReferences := false err := validateReferenceFields(ko) - if err == nil { - err = resolveReferenceForTargetKeyID(ctx, apiReader, namespace, ko) + if fieldHasReferences, err := rm.resolveReferenceForTargetKeyID(ctx, apiReader, namespace, ko); err != nil { + return &resource{ko}, (resourceHasReferences || fieldHasReferences), err + } else { + resourceHasReferences = resourceHasReferences || fieldHasReferences } - // If there was an error while resolving any reference, reset all the - // resolved values so that they do not get persisted inside etcd - if err != nil { - ko = rm.concreteResource(res).ko.DeepCopy() - } - if hasNonNilReferences(ko) { - return ackcondition.WithReferencesResolvedCondition(&resource{ko}, err) - } - return &resource{ko}, err + return &resource{ko}, resourceHasReferences, err } // validateReferenceFields validates the reference field and corresponding // identifier field. func validateReferenceFields(ko *svcapitypes.Alias) error { + if ko.Spec.TargetKeyRef != nil && ko.Spec.TargetKeyID != nil { return ackerr.ResourceReferenceAndIDNotSupportedFor("TargetKeyID", "TargetKeyRef") } @@ -73,34 +83,30 @@ func validateReferenceFields(ko *svcapitypes.Alias) error { return nil } -// hasNonNilReferences returns true if resource contains a reference to another -// resource -func hasNonNilReferences(ko *svcapitypes.Alias) bool { - return false || (ko.Spec.TargetKeyRef != nil) -} - // resolveReferenceForTargetKeyID reads the resource referenced // from TargetKeyRef field and sets the TargetKeyID -// from referenced resource -func resolveReferenceForTargetKeyID( +// from referenced resource. Returns a boolean indicating whether a reference +// contains references, or an error +func (rm *resourceManager) resolveReferenceForTargetKeyID( ctx context.Context, apiReader client.Reader, namespace string, ko *svcapitypes.Alias, -) error { +) (hasReferences bool, err error) { if ko.Spec.TargetKeyRef != nil && ko.Spec.TargetKeyRef.From != nil { + hasReferences = true arr := ko.Spec.TargetKeyRef.From - if arr == nil || arr.Name == nil || *arr.Name == "" { - return fmt.Errorf("provided resource reference is nil or empty: TargetKeyRef") + if arr.Name == nil || *arr.Name == "" { + return hasReferences, fmt.Errorf("provided resource reference is nil or empty: TargetKeyRef") } obj := &svcapitypes.Key{} if err := getReferencedResourceState_Key(ctx, apiReader, obj, *arr.Name, namespace); err != nil { - return err + return hasReferences, err } ko.Spec.TargetKeyID = (*string)(obj.Status.KeyID) } - return nil + return hasReferences, nil } // getReferencedResourceState_Key looks up whether a referenced resource diff --git a/pkg/resource/alias/resource.go b/pkg/resource/alias/resource.go index a43410d..08c8f4b 100644 --- a/pkg/resource/alias/resource.go +++ b/pkg/resource/alias/resource.go @@ -45,7 +45,7 @@ func (r *resource) Identifiers() acktypes.AWSResourceIdentifiers { } // IsBeingDeleted returns true if the Kubernetes resource has a non-zero -// deletion timestemp +// deletion timestamp func (r *resource) IsBeingDeleted() bool { return !r.ko.DeletionTimestamp.IsZero() } diff --git a/pkg/resource/grant/references.go b/pkg/resource/grant/references.go index 499b52b..f89eca4 100644 --- a/pkg/resource/grant/references.go +++ b/pkg/resource/grant/references.go @@ -24,46 +24,56 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1" - ackcondition "github.com/aws-controllers-k8s/runtime/pkg/condition" ackerr "github.com/aws-controllers-k8s/runtime/pkg/errors" acktypes "github.com/aws-controllers-k8s/runtime/pkg/types" svcapitypes "github.com/aws-controllers-k8s/kms-controller/apis/v1alpha1" ) +// ClearResolvedReferences removes any reference values that were made +// concrete in the spec. It returns a copy of the input AWSResource which +// contains the original *Ref values, but none of their respective concrete +// values. +func (rm *resourceManager) ClearResolvedReferences(res acktypes.AWSResource) acktypes.AWSResource { + ko := rm.concreteResource(res).ko.DeepCopy() + + if ko.Spec.KeyRef != nil { + ko.Spec.KeyID = nil + } + + return &resource{ko} +} + // ResolveReferences finds if there are any Reference field(s) present -// inside AWSResource passed in the parameter and attempts to resolve -// those reference field(s) into target field(s). -// It returns an AWSResource with resolved reference(s), and an error if the -// passed AWSResource's reference field(s) cannot be resolved. -// This method also adds/updates the ConditionTypeReferencesResolved for the -// AWSResource. +// inside AWSResource passed in the parameter and attempts to resolve those +// reference field(s) into their respective target field(s). It returns a +// copy of the input AWSResource with resolved reference(s), a boolean which +// is set to true if the resource contains any references (regardless of if +// they are resolved successfully) and an error if the passed AWSResource's +// reference field(s) could not be resolved. func (rm *resourceManager) ResolveReferences( ctx context.Context, apiReader client.Reader, res acktypes.AWSResource, -) (acktypes.AWSResource, error) { +) (acktypes.AWSResource, bool, error) { namespace := res.MetaObject().GetNamespace() - ko := rm.concreteResource(res).ko.DeepCopy() + ko := rm.concreteResource(res).ko + + resourceHasReferences := false err := validateReferenceFields(ko) - if err == nil { - err = resolveReferenceForKeyID(ctx, apiReader, namespace, ko) + if fieldHasReferences, err := rm.resolveReferenceForKeyID(ctx, apiReader, namespace, ko); err != nil { + return &resource{ko}, (resourceHasReferences || fieldHasReferences), err + } else { + resourceHasReferences = resourceHasReferences || fieldHasReferences } - // If there was an error while resolving any reference, reset all the - // resolved values so that they do not get persisted inside etcd - if err != nil { - ko = rm.concreteResource(res).ko.DeepCopy() - } - if hasNonNilReferences(ko) { - return ackcondition.WithReferencesResolvedCondition(&resource{ko}, err) - } - return &resource{ko}, err + return &resource{ko}, resourceHasReferences, err } // validateReferenceFields validates the reference field and corresponding // identifier field. func validateReferenceFields(ko *svcapitypes.Grant) error { + if ko.Spec.KeyRef != nil && ko.Spec.KeyID != nil { return ackerr.ResourceReferenceAndIDNotSupportedFor("KeyID", "KeyRef") } @@ -73,34 +83,30 @@ func validateReferenceFields(ko *svcapitypes.Grant) error { return nil } -// hasNonNilReferences returns true if resource contains a reference to another -// resource -func hasNonNilReferences(ko *svcapitypes.Grant) bool { - return false || (ko.Spec.KeyRef != nil) -} - // resolveReferenceForKeyID reads the resource referenced // from KeyRef field and sets the KeyID -// from referenced resource -func resolveReferenceForKeyID( +// from referenced resource. Returns a boolean indicating whether a reference +// contains references, or an error +func (rm *resourceManager) resolveReferenceForKeyID( ctx context.Context, apiReader client.Reader, namespace string, ko *svcapitypes.Grant, -) error { +) (hasReferences bool, err error) { if ko.Spec.KeyRef != nil && ko.Spec.KeyRef.From != nil { + hasReferences = true arr := ko.Spec.KeyRef.From - if arr == nil || arr.Name == nil || *arr.Name == "" { - return fmt.Errorf("provided resource reference is nil or empty: KeyRef") + if arr.Name == nil || *arr.Name == "" { + return hasReferences, fmt.Errorf("provided resource reference is nil or empty: KeyRef") } obj := &svcapitypes.Key{} if err := getReferencedResourceState_Key(ctx, apiReader, obj, *arr.Name, namespace); err != nil { - return err + return hasReferences, err } ko.Spec.KeyID = (*string)(obj.Status.KeyID) } - return nil + return hasReferences, nil } // getReferencedResourceState_Key looks up whether a referenced resource diff --git a/pkg/resource/grant/resource.go b/pkg/resource/grant/resource.go index ccecf43..6fd0f20 100644 --- a/pkg/resource/grant/resource.go +++ b/pkg/resource/grant/resource.go @@ -45,7 +45,7 @@ func (r *resource) Identifiers() acktypes.AWSResourceIdentifiers { } // IsBeingDeleted returns true if the Kubernetes resource has a non-zero -// deletion timestemp +// deletion timestamp func (r *resource) IsBeingDeleted() bool { return !r.ko.DeletionTimestamp.IsZero() } diff --git a/pkg/resource/key/references.go b/pkg/resource/key/references.go index c23c9c2..b647205 100644 --- a/pkg/resource/key/references.go +++ b/pkg/resource/key/references.go @@ -24,19 +24,29 @@ import ( svcapitypes "github.com/aws-controllers-k8s/kms-controller/apis/v1alpha1" ) +// ClearResolvedReferences removes any reference values that were made +// concrete in the spec. It returns a copy of the input AWSResource which +// contains the original *Ref values, but none of their respective concrete +// values. +func (rm *resourceManager) ClearResolvedReferences(res acktypes.AWSResource) acktypes.AWSResource { + ko := rm.concreteResource(res).ko.DeepCopy() + + return &resource{ko} +} + // ResolveReferences finds if there are any Reference field(s) present -// inside AWSResource passed in the parameter and attempts to resolve -// those reference field(s) into target field(s). -// It returns an AWSResource with resolved reference(s), and an error if the -// passed AWSResource's reference field(s) cannot be resolved. -// This method also adds/updates the ConditionTypeReferencesResolved for the -// AWSResource. +// inside AWSResource passed in the parameter and attempts to resolve those +// reference field(s) into their respective target field(s). It returns a +// copy of the input AWSResource with resolved reference(s), a boolean which +// is set to true if the resource contains any references (regardless of if +// they are resolved successfully) and an error if the passed AWSResource's +// reference field(s) could not be resolved. func (rm *resourceManager) ResolveReferences( ctx context.Context, apiReader client.Reader, res acktypes.AWSResource, -) (acktypes.AWSResource, error) { - return res, nil +) (acktypes.AWSResource, bool, error) { + return res, false, nil } // validateReferenceFields validates the reference field and corresponding @@ -44,9 +54,3 @@ func (rm *resourceManager) ResolveReferences( func validateReferenceFields(ko *svcapitypes.Key) error { return nil } - -// hasNonNilReferences returns true if resource contains a reference to another -// resource -func hasNonNilReferences(ko *svcapitypes.Key) bool { - return false -} diff --git a/pkg/resource/key/resource.go b/pkg/resource/key/resource.go index 25fd216..f0e56dc 100644 --- a/pkg/resource/key/resource.go +++ b/pkg/resource/key/resource.go @@ -45,7 +45,7 @@ func (r *resource) Identifiers() acktypes.AWSResourceIdentifiers { } // IsBeingDeleted returns true if the Kubernetes resource has a non-zero -// deletion timestemp +// deletion timestamp func (r *resource) IsBeingDeleted() bool { return !r.ko.DeletionTimestamp.IsZero() }