@@ -8,7 +8,6 @@ package pki
88
99import (
1010 "context"
11- "crypto/x509"
1211 "fmt"
1312 "log"
1413 "reflect"
@@ -22,15 +21,18 @@ import (
2221 "github.com/openshift/cluster-network-operator/pkg/names"
2322
2423 "github.com/openshift/library-go/pkg/controller/factory"
25- "github.com/openshift/library-go/pkg/crypto"
2624 "github.com/openshift/library-go/pkg/operator/certrotation"
25+ "github.com/openshift/library-go/pkg/pki"
2726 "github.com/pkg/errors"
2827
2928 features "github.com/openshift/api/features"
29+ configclient "github.com/openshift/client-go/config/clientset/versioned"
30+ configinformers "github.com/openshift/client-go/config/informers/externalversions"
3031 "github.com/openshift/library-go/pkg/operator/configobserver/featuregates"
3132 apierrors "k8s.io/apimachinery/pkg/api/errors"
3233 "k8s.io/apimachinery/pkg/types"
3334 utilruntime "k8s.io/apimachinery/pkg/util/runtime"
35+ "k8s.io/apiserver/pkg/authentication/user"
3436 "k8s.io/client-go/informers"
3537 "k8s.io/client-go/kubernetes"
3638 crclient "sigs.k8s.io/controller-runtime/pkg/client"
@@ -76,11 +78,15 @@ type PKIReconciler struct {
7678 status * statusmanager.StatusManager
7779
7880 // one PKI per CA
79- pkis map [types.NamespacedName ]* pki
81+ pkis map [types.NamespacedName ]* operatorPKI
8082 // For computing status
8183 pkiErrs map [types.NamespacedName ]error
8284
8385 certDuration time.Duration
86+
87+ // pkiProfileProvider is non-nil when the ConfigurablePKI feature gate is
88+ // enabled. It provides the PKI profile for certificate key configuration.
89+ pkiProfileProvider pki.PKIProfileProvider
8490}
8591
8692// The periodic resync interval.
@@ -101,14 +107,29 @@ func newPKIReconciler(mgr manager.Manager, status *statusmanager.StatusManager,
101107 certDuration = 2 * time .Hour
102108 }
103109
110+ var pkiProfileProvider pki.PKIProfileProvider
111+ if featureGates .Enabled (features .FeatureGateConfigurablePKI ) {
112+ cfgClient , err := configclient .NewForConfig (mgr .GetConfig ())
113+ if err != nil {
114+ return nil , fmt .Errorf ("failed to create config client for PKI informer: %w" , err )
115+ }
116+ cfgInformers := configinformers .NewSharedInformerFactory (cfgClient , 10 * time .Minute )
117+ pkiProfileProvider = pki .NewClusterPKIProfileProvider (cfgInformers .Config ().V1alpha1 ().PKIs ().Lister ())
118+
119+ stopCh := make (chan struct {})
120+ cfgInformers .Start (stopCh )
121+ cfgInformers .WaitForCacheSync (stopCh )
122+ }
123+
104124 return & PKIReconciler {
105125 mgr : mgr ,
106126 status : status ,
107127 clientset : clientset ,
108128
109- pkis : map [types.NamespacedName ]* pki {},
110- pkiErrs : map [types.NamespacedName ]error {},
111- certDuration : certDuration ,
129+ pkis : map [types.NamespacedName ]* operatorPKI {},
130+ pkiErrs : map [types.NamespacedName ]error {},
131+ certDuration : certDuration ,
132+ pkiProfileProvider : pkiProfileProvider ,
112133 }, nil
113134}
114135
@@ -139,7 +160,7 @@ func (r *PKIReconciler) Reconcile(ctx context.Context, request reconcile.Request
139160 }
140161 }
141162 if existing == nil {
142- existing , err = newPKI (obj , r .clientset , r .mgr , r .certDuration )
163+ existing , err = newPKI (obj , r .clientset , r .mgr , r .certDuration , r . pkiProfileProvider )
143164 if err != nil {
144165 log .Println (err )
145166 r .pkiErrs [request .NamespacedName ] =
@@ -179,15 +200,15 @@ func (r *PKIReconciler) setStatus() {
179200 }
180201}
181202
182- // pki is the internal type that represents a single PKI CRD. It manages the
203+ // operatorPKI is the internal type that represents a single PKI CRD. It manages the
183204// business of reconciling the certificate objects
184- type pki struct {
205+ type operatorPKI struct {
185206 spec netopv1.OperatorPKISpec
186207 controller factory.Controller
187208}
188209
189210// newPKI creates a CertRotationController for the supplied configuration
190- func newPKI (config * netopv1.OperatorPKI , clientset * kubernetes.Clientset , mgr manager.Manager , certDuration time.Duration ) (* pki , error ) {
211+ func newPKI (config * netopv1.OperatorPKI , clientset * kubernetes.Clientset , mgr manager.Manager , certDuration time.Duration , pkiProfileProvider pki. PKIProfileProvider ) (* operatorPKI , error ) {
191212 spec := config .Spec
192213
193214 // Ugly: the existing cache + informers used as part of the controller-manager
@@ -209,12 +230,14 @@ func newPKI(config *netopv1.OperatorPKI, clientset *kubernetes.Clientset, mgr ma
209230 AdditionalAnnotations : certrotation.AdditionalAnnotations {
210231 JiraComponent : names .ClusterNetworkOperatorJiraComponent ,
211232 },
212- Validity : 10 * OneYear ,
213- Refresh : 9 * OneYear ,
214- Informer : inf .Core ().V1 ().Secrets (),
215- Lister : inf .Core ().V1 ().Secrets ().Lister (),
216- Client : clientset .CoreV1 (),
217- EventRecorder : & eventrecorder.LoggingRecorder {},
233+ CertificateName : fmt .Sprintf ("network.%s-signer" , config .Name ),
234+ PKIProfileProvider : pkiProfileProvider ,
235+ Validity : 10 * OneYear ,
236+ Refresh : 9 * OneYear ,
237+ Informer : inf .Core ().V1 ().Secrets (),
238+ Lister : inf .Core ().V1 ().Secrets ().Lister (),
239+ Client : clientset .CoreV1 (),
240+ EventRecorder : & eventrecorder.LoggingRecorder {},
218241 },
219242 certrotation.CABundleConfigMap {
220243 Namespace : config .Namespace ,
@@ -233,15 +256,13 @@ func newPKI(config *netopv1.OperatorPKI, clientset *kubernetes.Clientset, mgr ma
233256 AdditionalAnnotations : certrotation.AdditionalAnnotations {
234257 JiraComponent : names .ClusterNetworkOperatorJiraComponent ,
235258 },
236- Validity : certDuration ,
237- Refresh : certDuration / 2 ,
238- CertCreator : & certrotation.ServingRotation {
259+ CertificateName : fmt .Sprintf ("network.%s-peer" , config .Name ),
260+ PKIProfileProvider : pkiProfileProvider ,
261+ Validity : certDuration ,
262+ Refresh : certDuration / 2 ,
263+ CertCreator : & certrotation.PeerRotation {
239264 Hostnames : func () []string { return []string {spec .TargetCert .CommonName } },
240-
241- // Force the certificate to also be client
242- CertificateExtensionFn : []crypto.CertificateExtensionFunc {
243- toClientCert ,
244- },
265+ UserInfo : & user.DefaultInfo {Name : spec .TargetCert .CommonName },
245266 },
246267 Lister : inf .Core ().V1 ().Secrets ().Lister (),
247268 Informer : inf .Core ().V1 ().Secrets (),
@@ -252,7 +273,7 @@ func newPKI(config *netopv1.OperatorPKI, clientset *kubernetes.Clientset, mgr ma
252273 nil ,
253274 )
254275
255- out := & pki {
276+ out := & operatorPKI {
256277 controller : cont ,
257278 }
258279 config .Spec .DeepCopyInto (& out .spec )
@@ -265,29 +286,7 @@ func newPKI(config *netopv1.OperatorPKI, clientset *kubernetes.Clientset, mgr ma
265286}
266287
267288// sync causes the underlying cert controller to try and reconcile
268- func (p * pki ) sync () error {
289+ func (p * operatorPKI ) sync () error {
269290 runOnceCtx := context .WithValue (context .Background (), certrotation .RunOnceContextKey , true ) //nolint:staticcheck
270291 return p .controller .Sync (runOnceCtx , nil )
271292}
272-
273- // toClientCert is a certificate "decorator" that adds ClientAuth to the
274- // list of ExtendedKeyUsages. This allows the generated certificate to be
275- // used for both client and server auth.
276- func toClientCert (cert * x509.Certificate ) error {
277- if len (cert .ExtKeyUsage ) == 0 {
278- return nil
279- }
280-
281- found := false
282- for _ , u := range cert .ExtKeyUsage {
283- if u == x509 .ExtKeyUsageClientAuth {
284- found = true
285- break
286- }
287- }
288-
289- if ! found {
290- cert .ExtKeyUsage = append (cert .ExtKeyUsage , x509 .ExtKeyUsageClientAuth )
291- }
292- return nil
293- }
0 commit comments