acme: Add API fields for ExternalAccountBinding
Signed-off-by: James Munnelly <james@munnelly.eu>
This commit is contained in:
parent
4073080089
commit
80bc253d74
@ -59,6 +59,44 @@ spec:
|
||||
email:
|
||||
description: Email is the email for this account
|
||||
type: string
|
||||
externalAccountBinding:
|
||||
description: ExternalAcccountBinding is a reference to a CA external
|
||||
account of the ACME server.
|
||||
type: object
|
||||
required:
|
||||
- keyAlgorithm
|
||||
- keyID
|
||||
- keySecretRef
|
||||
properties:
|
||||
keyAlgorithm:
|
||||
description: keyAlgorithm is the MAC key algorithm that the
|
||||
key is used for. Valid values are "HS256", "HS384" and "HS512".
|
||||
type: string
|
||||
keyID:
|
||||
description: keyID is the ID of the CA key that the External
|
||||
Account is bound to.
|
||||
type: string
|
||||
keySecretRef:
|
||||
description: keySecretRef is a Secret Key Selector referencing
|
||||
a data item in a Kubernetes Secret which holds the symmetric
|
||||
MAC key of the External Account Binding. The `key` is the
|
||||
index string that is paired with the key data in the Secret
|
||||
and should not be confused with the key data itself, or indeed
|
||||
with the External Account Binding keyID above. The secret
|
||||
key stored in the Secret **must** be un-padded, base64 URL
|
||||
encoded data.
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
key:
|
||||
description: The key of the secret to select from. Must
|
||||
be a valid secret key.
|
||||
type: string
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
privateKeySecretRef:
|
||||
description: PrivateKey is the name of a secret containing the private
|
||||
key for this user account.
|
||||
|
||||
@ -59,6 +59,44 @@ spec:
|
||||
email:
|
||||
description: Email is the email for this account
|
||||
type: string
|
||||
externalAccountBinding:
|
||||
description: ExternalAcccountBinding is a reference to a CA external
|
||||
account of the ACME server.
|
||||
type: object
|
||||
required:
|
||||
- keyAlgorithm
|
||||
- keyID
|
||||
- keySecretRef
|
||||
properties:
|
||||
keyAlgorithm:
|
||||
description: keyAlgorithm is the MAC key algorithm that the
|
||||
key is used for. Valid values are "HS256", "HS384" and "HS512".
|
||||
type: string
|
||||
keyID:
|
||||
description: keyID is the ID of the CA key that the External
|
||||
Account is bound to.
|
||||
type: string
|
||||
keySecretRef:
|
||||
description: keySecretRef is a Secret Key Selector referencing
|
||||
a data item in a Kubernetes Secret which holds the symmetric
|
||||
MAC key of the External Account Binding. The `key` is the
|
||||
index string that is paired with the key data in the Secret
|
||||
and should not be confused with the key data itself, or indeed
|
||||
with the External Account Binding keyID above. The secret
|
||||
key stored in the Secret **must** be un-padded, base64 URL
|
||||
encoded data.
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
key:
|
||||
description: The key of the secret to select from. Must
|
||||
be a valid secret key.
|
||||
type: string
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
privateKeySecretRef:
|
||||
description: PrivateKey is the name of a secret containing the private
|
||||
key for this user account.
|
||||
|
||||
@ -1886,6 +1886,44 @@ spec:
|
||||
email:
|
||||
description: Email is the email for this account
|
||||
type: string
|
||||
externalAccountBinding:
|
||||
description: ExternalAcccountBinding is a reference to a CA external
|
||||
account of the ACME server.
|
||||
type: object
|
||||
required:
|
||||
- keyAlgorithm
|
||||
- keyID
|
||||
- keySecretRef
|
||||
properties:
|
||||
keyAlgorithm:
|
||||
description: keyAlgorithm is the MAC key algorithm that the
|
||||
key is used for. Valid values are "HS256", "HS384" and "HS512".
|
||||
type: string
|
||||
keyID:
|
||||
description: keyID is the ID of the CA key that the External
|
||||
Account is bound to.
|
||||
type: string
|
||||
keySecretRef:
|
||||
description: keySecretRef is a Secret Key Selector referencing
|
||||
a data item in a Kubernetes Secret which holds the symmetric
|
||||
MAC key of the External Account Binding. The `key` is the
|
||||
index string that is paired with the key data in the Secret
|
||||
and should not be confused with the key data itself, or indeed
|
||||
with the External Account Binding keyID above. The secret
|
||||
key stored in the Secret **must** be un-padded, base64 URL
|
||||
encoded data.
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
key:
|
||||
description: The key of the secret to select from. Must
|
||||
be a valid secret key.
|
||||
type: string
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
privateKeySecretRef:
|
||||
description: PrivateKey is the name of a secret containing the private
|
||||
key for this user account.
|
||||
@ -3584,6 +3622,44 @@ spec:
|
||||
email:
|
||||
description: Email is the email for this account
|
||||
type: string
|
||||
externalAccountBinding:
|
||||
description: ExternalAcccountBinding is a reference to a CA external
|
||||
account of the ACME server.
|
||||
type: object
|
||||
required:
|
||||
- keyAlgorithm
|
||||
- keyID
|
||||
- keySecretRef
|
||||
properties:
|
||||
keyAlgorithm:
|
||||
description: keyAlgorithm is the MAC key algorithm that the
|
||||
key is used for. Valid values are "HS256", "HS384" and "HS512".
|
||||
type: string
|
||||
keyID:
|
||||
description: keyID is the ID of the CA key that the External
|
||||
Account is bound to.
|
||||
type: string
|
||||
keySecretRef:
|
||||
description: keySecretRef is a Secret Key Selector referencing
|
||||
a data item in a Kubernetes Secret which holds the symmetric
|
||||
MAC key of the External Account Binding. The `key` is the
|
||||
index string that is paired with the key data in the Secret
|
||||
and should not be confused with the key data itself, or indeed
|
||||
with the External Account Binding keyID above. The secret
|
||||
key stored in the Secret **must** be un-padded, base64 URL
|
||||
encoded data.
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
properties:
|
||||
key:
|
||||
description: The key of the secret to select from. Must
|
||||
be a valid secret key.
|
||||
type: string
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
privateKeySecretRef:
|
||||
description: PrivateKey is the name of a secret containing the private
|
||||
key for this user account.
|
||||
|
||||
@ -36,6 +36,11 @@ type ACMEIssuer struct {
|
||||
// +optional
|
||||
SkipTLSVerify bool `json:"skipTLSVerify,omitempty"`
|
||||
|
||||
// ExternalAcccountBinding is a reference to a CA external account of the ACME
|
||||
// server.
|
||||
// +optional
|
||||
ExternalAccountBinding *ACMEExternalAccountBinding `json:"externalAccountBinding,omitempty"`
|
||||
|
||||
// PrivateKey is the name of a secret containing the private key for this
|
||||
// user account.
|
||||
PrivateKey cmmeta.SecretKeySelector `json:"privateKeySecretRef"`
|
||||
@ -46,6 +51,26 @@ type ACMEIssuer struct {
|
||||
Solvers []ACMEChallengeSolver `json:"solvers,omitempty"`
|
||||
}
|
||||
|
||||
// ACMEExternalAcccountBinding is a reference to a CA external account of the ACME
|
||||
// server.
|
||||
type ACMEExternalAccountBinding struct {
|
||||
// keyID is the ID of the CA key that the External Account is bound to.
|
||||
KeyID string `json:"keyID"`
|
||||
|
||||
// keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes
|
||||
// Secret which holds the symmetric MAC key of the External Account Binding.
|
||||
// The `key` is the index string that is paired with the key data in the
|
||||
// Secret and should not be confused with the key data itself, or indeed with
|
||||
// the External Account Binding keyID above.
|
||||
// The secret key stored in the Secret **must** be un-padded, base64 URL
|
||||
// encoded data.
|
||||
Key cmmeta.SecretKeySelector `json:"keySecretRef"`
|
||||
|
||||
// keyAlgorithm is the MAC key algorithm that the key is used for. Valid
|
||||
// values are "HS256", "HS384" and "HS512".
|
||||
KeyAlgorithm string `json:"keyAlgorithm"`
|
||||
}
|
||||
|
||||
type ACMEChallengeSolver struct {
|
||||
// Selector selects a set of DNSNames on the Certificate resource that
|
||||
// should be solved using this challenge solver.
|
||||
|
||||
@ -291,9 +291,31 @@ func (in *ACMEChallengeSolverHTTP01IngressPodTemplate) DeepCopy() *ACMEChallenge
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ACMEExternalAccountBinding) DeepCopyInto(out *ACMEExternalAccountBinding) {
|
||||
*out = *in
|
||||
out.Key = in.Key
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ACMEExternalAccountBinding.
|
||||
func (in *ACMEExternalAccountBinding) DeepCopy() *ACMEExternalAccountBinding {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ACMEExternalAccountBinding)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ACMEIssuer) DeepCopyInto(out *ACMEIssuer) {
|
||||
*out = *in
|
||||
if in.ExternalAccountBinding != nil {
|
||||
in, out := &in.ExternalAccountBinding, &out.ExternalAccountBinding
|
||||
*out = new(ACMEExternalAccountBinding)
|
||||
**out = **in
|
||||
}
|
||||
out.PrivateKey = in.PrivateKey
|
||||
if in.Solvers != nil {
|
||||
in, out := &in.Solvers, &out.Solvers
|
||||
|
||||
@ -36,6 +36,11 @@ type ACMEIssuer struct {
|
||||
// +optional
|
||||
SkipTLSVerify bool `json:"skipTLSVerify,omitempty"`
|
||||
|
||||
// ExternalAcccountBinding is a reference to a CA external account of the ACME
|
||||
// server.
|
||||
// +optional
|
||||
ExternalAccountBinding *ACMEExternalAccountBinding `json:"externalAccountBinding,omitempty"`
|
||||
|
||||
// PrivateKey is the name of a secret containing the private key for this
|
||||
// user account.
|
||||
PrivateKey cmmeta.SecretKeySelector `json:"privateKeySecretRef"`
|
||||
@ -46,6 +51,24 @@ type ACMEIssuer struct {
|
||||
Solvers []ACMEChallengeSolver `json:"solvers,omitempty"`
|
||||
}
|
||||
|
||||
// ACMEExternalAcccountBinding is a reference to a CA external account of the ACME
|
||||
// server.
|
||||
type ACMEExternalAccountBinding struct {
|
||||
// keyID is the ID of the CA key that the External Account is bound to.
|
||||
KeyID string `json:"keyID"`
|
||||
|
||||
// keySecretRef is a Secret Key Selector referencing a data item in a Kubernetes
|
||||
// Secret which holds the symmetric MAC key of the External Account Binding.
|
||||
// The `key` is the index string that is paired with the key data in the
|
||||
// Secret and should not be confused with the key data itself, or indeed with
|
||||
// the External Account Binding keyID above.
|
||||
Key cmmeta.SecretKeySelector `json:"keySecretRef"`
|
||||
|
||||
// keyAlgorithm is the MAC key algorithm that the key is used for. Valid
|
||||
// values are "HS256", "HS384" and "HS512".
|
||||
KeyAlgorithm string `json:"keyAlgorithm"`
|
||||
}
|
||||
|
||||
type ACMEChallengeSolver struct {
|
||||
// Selector selects a set of DNSNames on the Certificate resource that
|
||||
// should be solved using this challenge solver.
|
||||
|
||||
@ -131,6 +131,16 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v1alpha2.ACMEExternalAccountBinding)(nil), (*acme.ACMEExternalAccountBinding)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha2_ACMEExternalAccountBinding_To_acme_ACMEExternalAccountBinding(a.(*v1alpha2.ACMEExternalAccountBinding), b.(*acme.ACMEExternalAccountBinding), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*acme.ACMEExternalAccountBinding)(nil), (*v1alpha2.ACMEExternalAccountBinding)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_acme_ACMEExternalAccountBinding_To_v1alpha2_ACMEExternalAccountBinding(a.(*acme.ACMEExternalAccountBinding), b.(*v1alpha2.ACMEExternalAccountBinding), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v1alpha2.ACMEIssuer)(nil), (*acme.ACMEIssuer)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha2_ACMEIssuer_To_acme_ACMEIssuer(a.(*v1alpha2.ACMEIssuer), b.(*acme.ACMEIssuer), scope)
|
||||
}); err != nil {
|
||||
@ -568,10 +578,41 @@ func Convert_acme_ACMEChallengeSolverHTTP01IngressPodTemplate_To_v1alpha2_ACMECh
|
||||
return autoConvert_acme_ACMEChallengeSolverHTTP01IngressPodTemplate_To_v1alpha2_ACMEChallengeSolverHTTP01IngressPodTemplate(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha2_ACMEExternalAccountBinding_To_acme_ACMEExternalAccountBinding(in *v1alpha2.ACMEExternalAccountBinding, out *acme.ACMEExternalAccountBinding, s conversion.Scope) error {
|
||||
out.KeyID = in.KeyID
|
||||
// TODO: Inefficient conversion - can we improve it?
|
||||
if err := s.Convert(&in.Key, &out.Key, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
out.KeyAlgorithm = in.KeyAlgorithm
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha2_ACMEExternalAccountBinding_To_acme_ACMEExternalAccountBinding is an autogenerated conversion function.
|
||||
func Convert_v1alpha2_ACMEExternalAccountBinding_To_acme_ACMEExternalAccountBinding(in *v1alpha2.ACMEExternalAccountBinding, out *acme.ACMEExternalAccountBinding, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha2_ACMEExternalAccountBinding_To_acme_ACMEExternalAccountBinding(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_acme_ACMEExternalAccountBinding_To_v1alpha2_ACMEExternalAccountBinding(in *acme.ACMEExternalAccountBinding, out *v1alpha2.ACMEExternalAccountBinding, s conversion.Scope) error {
|
||||
out.KeyID = in.KeyID
|
||||
// TODO: Inefficient conversion - can we improve it?
|
||||
if err := s.Convert(&in.Key, &out.Key, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
out.KeyAlgorithm = in.KeyAlgorithm
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_acme_ACMEExternalAccountBinding_To_v1alpha2_ACMEExternalAccountBinding is an autogenerated conversion function.
|
||||
func Convert_acme_ACMEExternalAccountBinding_To_v1alpha2_ACMEExternalAccountBinding(in *acme.ACMEExternalAccountBinding, out *v1alpha2.ACMEExternalAccountBinding, s conversion.Scope) error {
|
||||
return autoConvert_acme_ACMEExternalAccountBinding_To_v1alpha2_ACMEExternalAccountBinding(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha2_ACMEIssuer_To_acme_ACMEIssuer(in *v1alpha2.ACMEIssuer, out *acme.ACMEIssuer, s conversion.Scope) error {
|
||||
out.Email = in.Email
|
||||
out.Server = in.Server
|
||||
out.SkipTLSVerify = in.SkipTLSVerify
|
||||
out.ExternalAccountBinding = (*acme.ACMEExternalAccountBinding)(unsafe.Pointer(in.ExternalAccountBinding))
|
||||
// TODO: Inefficient conversion - can we improve it?
|
||||
if err := s.Convert(&in.PrivateKey, &out.PrivateKey, 0); err != nil {
|
||||
return err
|
||||
@ -589,6 +630,7 @@ func autoConvert_acme_ACMEIssuer_To_v1alpha2_ACMEIssuer(in *acme.ACMEIssuer, out
|
||||
out.Email = in.Email
|
||||
out.Server = in.Server
|
||||
out.SkipTLSVerify = in.SkipTLSVerify
|
||||
out.ExternalAccountBinding = (*v1alpha2.ACMEExternalAccountBinding)(unsafe.Pointer(in.ExternalAccountBinding))
|
||||
// TODO: Inefficient conversion - can we improve it?
|
||||
if err := s.Convert(&in.PrivateKey, &out.PrivateKey, 0); err != nil {
|
||||
return err
|
||||
|
||||
@ -291,9 +291,31 @@ func (in *ACMEChallengeSolverHTTP01IngressPodTemplate) DeepCopy() *ACMEChallenge
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ACMEExternalAccountBinding) DeepCopyInto(out *ACMEExternalAccountBinding) {
|
||||
*out = *in
|
||||
out.Key = in.Key
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ACMEExternalAccountBinding.
|
||||
func (in *ACMEExternalAccountBinding) DeepCopy() *ACMEExternalAccountBinding {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ACMEExternalAccountBinding)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ACMEIssuer) DeepCopyInto(out *ACMEIssuer) {
|
||||
*out = *in
|
||||
if in.ExternalAccountBinding != nil {
|
||||
in, out := &in.ExternalAccountBinding, &out.ExternalAccountBinding
|
||||
*out = new(ACMEExternalAccountBinding)
|
||||
**out = **in
|
||||
}
|
||||
out.PrivateKey = in.PrivateKey
|
||||
if in.Solvers != nil {
|
||||
in, out := &in.Solvers, &out.Solvers
|
||||
|
||||
@ -103,6 +103,20 @@ func ValidateACMEIssuerConfig(iss *cmacme.ACMEIssuer, fldPath *field.Path) field
|
||||
if len(iss.Server) == 0 {
|
||||
el = append(el, field.Required(fldPath.Child("server"), "acme server URL is a required field"))
|
||||
}
|
||||
|
||||
if eab := iss.ExternalAccountBinding; eab != nil {
|
||||
eabFldPath := fldPath.Child("externalAccountBinding")
|
||||
if len(eab.KeyID) == 0 {
|
||||
el = append(el, field.Required(eabFldPath.Child("keyID"), "the keyID field is required when using externalAccountBinding"))
|
||||
}
|
||||
|
||||
el = append(el, ValidateSecretKeySelector(&eab.Key, eabFldPath.Child("keySecretRef"))...)
|
||||
|
||||
if len(eab.KeyAlgorithm) == 0 {
|
||||
el = append(el, field.Required(eabFldPath.Child("keyAlgorithm"), "the keyAlgorithm field is required when using externalAccountBinding"))
|
||||
}
|
||||
}
|
||||
|
||||
for i, sol := range iss.Solvers {
|
||||
el = append(el, ValidateACMEIssuerChallengeSolverConfig(&sol, fldPath.Child("solvers").Index(i))...)
|
||||
}
|
||||
|
||||
@ -144,6 +144,27 @@ func TestValidateACMEIssuerConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"acme solver with empty external account binding fields": {
|
||||
spec: &cmacme.ACMEIssuer{
|
||||
Email: "valid-email",
|
||||
Server: "valid-server",
|
||||
PrivateKey: validSecretKeyRef,
|
||||
ExternalAccountBinding: &cmacme.ACMEExternalAccountBinding{},
|
||||
Solvers: []cmacme.ACMEChallengeSolver{
|
||||
{
|
||||
DNS01: &cmacme.ACMEChallengeSolverDNS01{
|
||||
CloudDNS: &validCloudDNSProvider,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
errs: []*field.Error{
|
||||
field.Required(fldPath.Child("externalAccountBinding.keyID"), "the keyID field is required when using externalAccountBinding"),
|
||||
field.Required(fldPath.Child("externalAccountBinding.keySecretRef.name"), "secret name is required"),
|
||||
field.Required(fldPath.Child("externalAccountBinding.keySecretRef.key"), "secret key is required"),
|
||||
field.Required(fldPath.Child("externalAccountBinding.keyAlgorithm"), "the keyAlgorithm field is required when using externalAccountBinding"),
|
||||
},
|
||||
},
|
||||
"acme solver with missing http01 config type": {
|
||||
spec: &cmacme.ACMEIssuer{
|
||||
Email: "valid-email",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user