func NewKeystoneAuth()

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
}