diff --git a/VERSION b/VERSION index b1d18bc..aaf7425 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.3.0 +v2.3.1 diff --git a/apis/certmanager/v1beta1/digicertissuer_types.go b/apis/certmanager/v1beta1/digicertissuer_types.go index 4c2a0bd..2dc1352 100644 --- a/apis/certmanager/v1beta1/digicertissuer_types.go +++ b/apis/certmanager/v1beta1/digicertissuer_types.go @@ -31,6 +31,8 @@ type DigicertIssuerSpec struct { Provisioner DigicertProvisioner `json:"provisioner"` } +// +kubebuilder:validation:XValidation:message="only one of validityDays and validityYears can be set.",rule="has(self.validityDays) && !has(self.validityYears) || !has(self.validityDays) && has(self.validityYears)" + // DigiCertProvisioner contains the DigiCert provisioner configuration. type DigicertProvisioner struct { // APITokenReference references a secret in the same namespace containing the DigiCert API token. @@ -49,7 +51,11 @@ type DigicertProvisioner struct { // OrganizationUnits is the list of organizational units. OrganizationUnits []string `json:"organizationUnits,omitempty"` - // ValidityYears is the validity of the certificate in years. + // ValidityDays is the validity of the order and certificate in days. Overrides ValidityYears if set. + ValidityDays *int `json:"validityDays,omitempty"` + + // ValidityYears is the validity of the order and certificate in years. Defaults to 1 year if not set. + // Can be overridden by ValidityDays. ValidityYears *int `json:"validityYears,omitempty"` // DisableRenewalNotifications disables email renewal notifications for expiring certificates. @@ -151,7 +157,7 @@ const ( // +kubebuilder:object:root=true // +kubebuilder:subresource:status -// +kubebuilder:printcolumn:name="Ready",type=boolean,JSONPath=`.status.conditions[?(@.type=="Ready")].status` +// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status` // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" // DigicertIssuer is the Schema for the digicertissuers API diff --git a/apis/certmanager/v1beta1/zz_generated.deepcopy.go b/apis/certmanager/v1beta1/zz_generated.deepcopy.go index bcb024d..a522d13 100644 --- a/apis/certmanager/v1beta1/zz_generated.deepcopy.go +++ b/apis/certmanager/v1beta1/zz_generated.deepcopy.go @@ -158,6 +158,11 @@ func (in *DigicertProvisioner) DeepCopyInto(out *DigicertProvisioner) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.ValidityDays != nil { + in, out := &in.ValidityDays, &out.ValidityDays + *out = new(int) + **out = **in + } if in.ValidityYears != nil { in, out := &in.ValidityYears, &out.ValidityYears *out = new(int) diff --git a/config/crd/bases/certmanager.cloud.sap_digicertissuers.yaml b/config/crd/bases/certmanager.cloud.sap_digicertissuers.yaml index eec7d78..9b17c69 100644 --- a/config/crd/bases/certmanager.cloud.sap_digicertissuers.yaml +++ b/config/crd/bases/certmanager.cloud.sap_digicertissuers.yaml @@ -1,11 +1,9 @@ - --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.3.0 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.17.0 name: digicertissuers.certmanager.cloud.sap spec: group: certmanager.cloud.sap @@ -19,7 +17,7 @@ spec: - additionalPrinterColumns: - jsonPath: .status.conditions[?(@.type=="Ready")].status name: Ready - type: boolean + type: string - jsonPath: .metadata.creationTimestamp name: Age type: date @@ -29,14 +27,19 @@ spec: description: DigicertIssuer is the Schema for the digicertissuers API properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds type: string metadata: type: object @@ -78,8 +81,9 @@ spec: description: OrganizationID is the ID of the organization in Digicert. type: integer organizationName: - description: OrganizationName is the name of the organization - in Digicert. If specified takes precedence over OrganizationID. + description: |- + OrganizationName is the name of the organization in Digicert. + If specified takes precedence over OrganizationID. type: string organizationUnits: description: OrganizationUnits is the list of organizational units. @@ -93,13 +97,22 @@ spec: skipApproval: description: SkipApproval skips the approval of the certificate. type: boolean + validityDays: + description: ValidityDays is the validity of the order and certificate + in days. Overrides ValidityYears if set. + type: integer validityYears: - description: ValidityYears is the validity of the certificate - in years. + description: |- + ValidityYears is the validity of the order and certificate in years. Defaults to 1 year if not set. + Can be overridden by ValidityDays. type: integer required: - apiTokenReference type: object + x-kubernetes-validations: + - message: only one of validityDays and validityYears can be set. + rule: has(self.validityDays) && !has(self.validityYears) || !has(self.validityDays) + && has(self.validityYears) url: description: Optional URL is the DigiCert cert-central API. type: string @@ -116,17 +129,20 @@ spec: description: DigicertIssuerCondition ... properties: lastTransitionTime: - description: LastTransitionTime is the timestamp corresponding - to the last status change of this condition. + description: |- + LastTransitionTime is the timestamp corresponding to the last status + change of this condition. format: date-time type: string message: - description: Message is a human readable description of the - details of the last transition, complementing reason. + description: |- + Message is a human readable description of the details of the last + transition, complementing reason. type: string reason: - description: Reason is a brief machine readable explanation - for the condition's last transition. + description: |- + Reason is a brief machine readable explanation for the condition's last + transition. type: string status: allOf: @@ -159,9 +175,3 @@ spec: storage: true subresources: status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 8dfcea2..7ee9086 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -1,9 +1,7 @@ - --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - creationTimestamp: null name: digicert-issuer-role rules: - apiGroups: @@ -13,6 +11,14 @@ rules: verbs: - create - patch +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch - apiGroups: - cert-manager.io resources: @@ -20,9 +26,9 @@ rules: verbs: - get - list + - patch - update - watch - - patch - apiGroups: - cert-manager.io resources: @@ -51,11 +57,3 @@ rules: - get - patch - update -- apiGroups: - - "" - resources: - - secrets - verbs: - - get - - list - - watch diff --git a/controllers/certmanager/certificaterequest_controller.go b/controllers/certmanager/certificaterequest_controller.go index 8573530..71f5a6a 100644 --- a/controllers/certmanager/certificaterequest_controller.go +++ b/controllers/certmanager/certificaterequest_controller.go @@ -69,7 +69,7 @@ func (r *CertificateRequestReconciler) SetupWithManager(mgr ctrl.Manager) error Complete(r) } -// +kubebuilder:rbac:groups=cert-manager.io,resources=certificaterequests,verbs=get;list;watch;update +// +kubebuilder:rbac:groups=cert-manager.io,resources=certificaterequests,verbs=get;list;watch;update;patch // +kubebuilder:rbac:groups=cert-manager.io,resources=certificaterequests/status,verbs=get;update;patch // Reconcile will read and validate a DigicertIssuer resource associated to the diff --git a/docs/apidocs/api.md b/docs/apidocs/api.md index b2a96ac..71833b6 100644 --- a/docs/apidocs/api.md +++ b/docs/apidocs/api.md @@ -81,7 +81,8 @@ DigiCertProvisioner contains the DigiCert provisioner configuration. | organizationID | OrganizationID is the ID of the organization in Digicert. | *int | false | | organizationName | OrganizationName is the name of the organization in Digicert. If specified takes precedence over OrganizationID. | string | false | | organizationUnits | OrganizationUnits is the list of organizational units. | []string | false | -| validityYears | ValidityYears is the validity of the certificate in years. | *int | false | +| validityDays | ValidityDays is the validity of the order and certificate in days. Overrides ValidityYears if set. | *int | false | +| validityYears | ValidityYears is the validity of the order and certificate in years. Defaults to 1 year if not set. Can be overridden by ValidityDays. | *int | false | | disableRenewalNotifications | DisableRenewalNotifications disables email renewal notifications for expiring certificates. | *bool | false | | paymentMethod | PaymentMethod is the configured payment method in the Digicert account. | string | false | | skipApproval | SkipApproval skips the approval of the certificate. | *bool | false | diff --git a/go.mod b/go.mod index 1004c4a..917bfde 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/onsi/ginkgo/v2 v2.22.2 github.com/onsi/gomega v1.36.2 github.com/prometheus/client_golang v1.20.5 - github.com/sapcc/go-certcentral v1.2.5 + github.com/sapcc/go-certcentral v1.4.0 k8s.io/api v0.32.0 k8s.io/apimachinery v0.32.0 k8s.io/client-go v0.32.0 diff --git a/go.sum b/go.sum index b154212..69b3152 100644 --- a/go.sum +++ b/go.sum @@ -97,8 +97,8 @@ github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoG github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sapcc/go-certcentral v1.2.5 h1:CdUxppuXVFVqk2jMNvgaIKayv0ev9hn0+T8h/bH6MlU= -github.com/sapcc/go-certcentral v1.2.5/go.mod h1:Asbvss/5uWi2Ko5UkM24D2DjMHbV3Exl+OlvQmxcvww= +github.com/sapcc/go-certcentral v1.4.0 h1:v+ubmF5IREa9mYTcNKaKCp8c1CRCpX+xz637vC2LYQk= +github.com/sapcc/go-certcentral v1.4.0/go.mod h1:Asbvss/5uWi2Ko5UkM24D2DjMHbV3Exl+OlvQmxcvww= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= diff --git a/pkg/provisioners/certcentral.go b/pkg/provisioners/certcentral.go index b90635b..d9389aa 100644 --- a/pkg/provisioners/certcentral.go +++ b/pkg/provisioners/certcentral.go @@ -20,6 +20,7 @@ import ( "context" "crypto/x509" "fmt" + certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" "github.com/sapcc/digicert-issuer/apis/certmanager/v1beta1" certcentral "github.com/sapcc/go-certcentral" @@ -31,8 +32,9 @@ type CertCentral struct { name string client *certcentral.Client - validityYears, - organizationID int + validityDays *int + validityYears *int + organizationID int caCertID string organizationalUnits []string skipApproval, @@ -67,9 +69,15 @@ func New(issuer *v1beta1.DigicertIssuer, apiToken string) (*CertCentral, error) organizationID = org.ID } - validityYears := defaultValidityYears - if issuer.Spec.Provisioner.ValidityYears != nil { - validityYears = *issuer.Spec.Provisioner.ValidityYears + validityYears := issuer.Spec.Provisioner.ValidityYears + validityDays := issuer.Spec.Provisioner.ValidityDays + if validityYears != nil && validityDays != nil { + return nil, fmt.Errorf("can not handle both validityYears and validityDays") + } + + if validityYears == nil && validityDays == nil { + v := defaultValidityYears + validityYears = &v } orgUnits := make([]string, 0) @@ -106,6 +114,7 @@ func New(issuer *v1beta1.DigicertIssuer, apiToken string) (*CertCentral, error) name: fmt.Sprintf("%s/%s", issuer.GetName(), issuer.GetNamespace()), client: client, validityYears: validityYears, + validityDays: validityDays, organizationID: organizationID, caCertID: issuer.Spec.Provisioner.CACertID, organizationalUnits: orgUnits, @@ -132,6 +141,14 @@ func (c *CertCentral) Sign(ctx context.Context, cr *certmanagerv1.CertificateReq sans = append(sans, ipAddr.String()) } + orderValidity := certcentral.OrderValidity{} + if c.validityDays != nil { + orderValidity.Days = *c.validityDays + } + if c.validityYears != nil { + orderValidity.Years = *c.validityYears + } + orderResponse, err := c.client.SubmitOrder(certcentral.Order{ Certificate: certcentral.Certificate{ CommonName: getCommonName(certReq), @@ -142,7 +159,7 @@ func (c *CertCentral) Sign(ctx context.Context, cr *certmanagerv1.CertificateReq CaCertID: c.caCertID, OrganizationUnits: c.organizationalUnits, }, - ValidityYears: c.validityYears, + OrderValidity: orderValidity, DisableRenewalNotifications: c.disableRenewalNotifications, PaymentMethod: c.paymentMethod, SkipApproval: c.skipApproval,