in pkg/identity/keystone/keystone.go [403:511]
func NewKeystoneAuth(c *Config) (*KeystoneAuth, error) {
keystoneClient, err := createKeystoneClient(c.KeystoneURL, c.KeystoneCA)
if err != nil {
return nil, fmt.Errorf("failed to initialize keystone client: %v", err)
}
var k8sClient *kubernetes.Clientset
if c.PolicyConfigMapName != "" || c.SyncConfigMapName != "" || c.SyncConfigFile != "" {
k8sClient, err = createKubernetesClient(c.Kubeconfig)
if err != nil {
return nil, fmt.Errorf("failed to get kubernetes client: %v", err)
}
}
// Get policy definition either from a policy file or the policy configmap. Policy file takes precedence
// over the configmap, but the policy definition will be refreshed based on the configmap change on-the-fly. It
// is possible that both are not provided, in this case, the keytone webhook authorization will always return deny.
var policy policyList
if c.PolicyConfigMapName != "" {
cm, err := k8sClient.CoreV1().ConfigMaps(cmNamespace).Get(context.TODO(), c.PolicyConfigMapName, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("failed to get configmap %s: %v", c.PolicyConfigMapName, err)
}
if err := json.Unmarshal([]byte(cm.Data["policies"]), &policy); err != nil {
return nil, fmt.Errorf("failed to parse policies defined in the configmap %s: %v", c.PolicyConfigMapName, err)
}
}
if c.PolicyFile != "" {
policy, err = newFromFile(c.PolicyFile)
if err != nil {
return nil, fmt.Errorf("failed to extract policy from policy file %s: %v", c.PolicyFile, err)
}
}
if len(policy) > 0 {
output, err := json.MarshalIndent(policy, "", " ")
if err == nil {
klog.V(4).Infof("Policy %s", string(output))
} else {
return nil, err
}
}
// Get sync config either from a sync config file or the sync configmap. Sync config file takes precedence
// over the configmap, but the sync config definition will be refreshed based on the configmap change on-the-fly. It
// is possible that both are not provided, in this case, the keytone webhook authenticator will not synchronize data.
var sc *syncConfig
if c.SyncConfigMapName != "" {
cm, err := k8sClient.CoreV1().ConfigMaps(cmNamespace).Get(context.TODO(), c.SyncConfigMapName, metav1.GetOptions{})
if err != nil {
klog.Errorf("configmap get err #%v ", err)
return nil, fmt.Errorf("failed to get configmap %s: %v", c.SyncConfigMapName, err)
}
newConfig := newSyncConfig()
sc = &newConfig
if err := yaml.Unmarshal([]byte(cm.Data["syncConfig"]), sc); err != nil {
klog.Errorf("Unmarshal: %v", err)
return nil, fmt.Errorf("failed to parse sync config defined in the configmap %s: %v", c.SyncConfigMapName, err)
}
}
if c.SyncConfigFile != "" {
sc, err = newSyncConfigFromFile(c.SyncConfigFile)
if err != nil {
return nil, fmt.Errorf("failed to extract data from sync config file %s: %v", c.SyncConfigFile, err)
}
}
if sc != nil {
// Validate that config data is correct
sc.validate()
}
keystoneAuth := &KeystoneAuth{
authn: &Authenticator{keystoner: NewKeystoner(keystoneClient)},
authz: &Authorizer{authURL: c.KeystoneURL, client: keystoneClient, pl: policy},
syncer: &Syncer{k8sClient: k8sClient, syncConfig: sc},
k8sClient: k8sClient,
config: c,
stopCh: make(chan struct{}),
}
if k8sClient != nil {
queue := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter())
kubeInformerFactory := informers.NewSharedInformerFactory(k8sClient, time.Minute*5)
cmInformer := kubeInformerFactory.Core().V1().ConfigMaps()
cmInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: keystoneAuth.enqueueConfigMap,
UpdateFunc: func(old, new interface{}) {
newIng := new.(*apiv1.ConfigMap)
oldIng := old.(*apiv1.ConfigMap)
if newIng.ResourceVersion == oldIng.ResourceVersion {
// Periodic resync will send update events for all known ConfigMaps.
// Two different versions of the same ConfigMap will always have different RVs.
return
}
keystoneAuth.enqueueConfigMap(new)
},
DeleteFunc: keystoneAuth.enqueueConfigMap,
})
keystoneAuth.informer = kubeInformerFactory
keystoneAuth.cmLister = cmInformer.Lister()
keystoneAuth.cmListerSynced = cmInformer.Informer().HasSynced
keystoneAuth.queue = queue
}
return keystoneAuth, nil
}