func()

in appconfigmgrv2/api/webhooks/builtins/pod_webhook.go [261:472]


func (a *podAnnotator) handleGCPVault(ctx context.Context, pod *corev1.Pod, app *appconfig.AppEnvConfigTemplateV2) error {
	log.Info("podAnnotator:handleGCPVault")

	var (
		caVolName  = VAULT_CA_SECRET_NAME + "-vol"
		gcpVolName = "google-auth-token"
		vaultInfo  = app.Spec.Auth.GCPAccess.VaultInfo
	)

	log.Info("handleGCPVault:loadConfig")

	// read vaultInfo from AppEnvConfigTemplateV2 spec
	if vaultInfo == nil {
		return fmt.Errorf("vaultInfo not configured")
	}

	if vaultInfo.ServiceAccount == "" {
		return fmt.Errorf("vaultInfo missing serviceAccount field")
	}

	if vaultInfo.ServiceAccount != pod.Spec.ServiceAccountName {
		return fmt.Errorf("pod serviceAccountName does not equal vaultInfo serviceAccount field")
	}
	// TODO - This did not work so we introduced a check and this might be outside vault
	//pod.Spec.ServiceAccountName = vaultInfo.ServiceAccount

	if vaultInfo.Path == "" {
		return fmt.Errorf("vaultInfo missing gcpPath field")
	}

	// construct image name and tag from env
	imageBuild := os.Getenv("CONTROLLER_BUILD")
	if imageBuild == "" {
		imageBuild = "latest"
	}
	imageRegistry := os.Getenv("CONTROLLER_REGISTRY")
	if imageRegistry == "" {
		imageRegistry = "gcr.io/anthos-appconfig"
	}
	image := fmt.Sprintf("%s/vault-api-helper:%s", imageRegistry, imageBuild)

	// get vault configMap, validate
	log.Info("handleGCPVault:loadConfig", "ConfigMap", VAULT_CONFIGMAP_NAME)
	config, err := getConfigMap(ctx, VAULT_CONFIGMAP_NAME, TODO_FIND_NAMESPACE)
	if err != nil {
		return err
	}

	if config.Data["vault-addr"] == "" {
		return fmt.Errorf("ConfigMap missing vault-addr")
	}

	if config.Data["vault-cluster-path"] == "" {
		return fmt.Errorf("ConfigMap missing vault-cluster-path")
	}

	if config.Data["gcp-vault-path"] == "" {
		return fmt.Errorf("ConfigMap missing gcp-vault-path")
	}

	//// get provided serviceAccount JWT token
	//log.Info("handleGCPVault:loadConfig", "ServiceAccount", vaultInfo.ServiceAccount)
	//ksaToken, err := svcAcctJWT(ctx, vaultInfo.ServiceAccount, app.Namespace)
	//if err != nil {
	//	return err
	//}
	//log.Info("handleGCPVault:loadConfig", "Token", len(ksaToken))
	//
	//VAULT_ADDITIONAL_SECRET := "vault-helper-info"
	//secretDataMap := &map[string]string{
	//	"ksa.token": ksaToken,
	//}

	//createSecret(context.TODO(), VAULT_ADDITIONAL_SECRET, app.Namespace, secretDataMap)
	// copy vault CA cert into app namespace

	VAULT_CA_SECRET_NAME := "vault-ca"
	// add vault CA cert secret to pod volumes
	log.Info("handleGCPVault:applyConfig", "Volume", VAULT_CA_SECRET_NAME)
	injectVolume(pod, corev1.Volume{
		Name: caVolName,
		VolumeSource: corev1.VolumeSource{
			Secret: &corev1.SecretVolumeSource{
				SecretName: VAULT_CA_SECRET_NAME,
			},
		},
	})

	var envVar = []corev1.EnvVar{
		{
			Name: "MY_POD_NAMESPACE",
			ValueFrom: &corev1.EnvVarSource{
				FieldRef: &corev1.ObjectFieldSelector{
					APIVersion: "v1",
					FieldPath:  "metadata.namespace",
				},
			},
		},

		{
			Name: "MY_POD_SERVICE_ACCOUNT",
			ValueFrom: &corev1.EnvVarSource{
				FieldRef: &corev1.ObjectFieldSelector{
					APIVersion: "v1",
					FieldPath:  "spec.serviceAccountName",
				},
			},
		},
		{
			Name:  "INIT_GCP_KEYPATH",
			Value: fmt.Sprintf("%s/key/%s", config.Data["gcp-vault-path"], vaultInfo.Roleset),
		},
		{
			Name:  "INIT_K8S_KEYPATH",
			Value: fmt.Sprintf("%s", config.Data["vault-cluster-path"]),
		},
		{
			Name:  "INIT_K8S_ROLE",
			Value: fmt.Sprintf("%s", vaultInfo.Roleset),
		},
		{
			Name:  "VAULT_ADDR",
			Value: config.Data["vault-addr"],
		},
		{
			Name:  "VAULT_CAPATH",
			Value: "/var/run/secrets/vault/ca.pem",
		},
		{
			Name:  "GOOGLE_APPLICATION_CREDENTIALS",
			Value: "/var/run/secrets/google/token/key.json",
		},
		{
			Name:  "INIT_K8S_TOKEN_KEYPATH",
			Value: "/var/run/secrets/kubernetes.io/serviceaccount/token",
		},
	}

	log.Info("handleGCPVault:applyConfig", "getVolumeMountForToken", gcpVolName)
	serviceAccountVolumeMount := getVolumeMountsInExistingContainers(pod)
	if serviceAccountVolumeMount == nil {
		panic(errors.New("Failed to find serviceAccountVolumeMount"))
	}
	log.Info("handleGCPVault:injectInitContainer", "Container", "vault-gcp-auth")

	// inject vault-gcp init container
	injectInitContainer(pod, corev1.Container{
		Name:            "vault-gcp-auth",
		Image:           image,
		ImagePullPolicy: corev1.PullAlways,
		Env:             envVar,
		VolumeMounts: []corev1.VolumeMount{
			{
				Name:      caVolName,
				MountPath: "/var/run/secrets/vault",
			},
			{
				Name:      gcpVolName,
				MountPath: "/var/run/secrets/google/token",
			},
			*serviceAccountVolumeMount,
		},
	})

	// inject vault-gcp cycle container
	injectContainer(pod, corev1.Container{
		Name:            "vault-gcp-cycle",
		Image:           image,
		ImagePullPolicy: corev1.PullAlways,
		Command:         []string{"./app", "--mode", "GCP-RECYCLE"},
		Env:             envVar,
		VolumeMounts: []corev1.VolumeMount{
			{
				Name:      caVolName,
				MountPath: "/var/run/secrets/vault",
			},
			{
				Name:      gcpVolName,
				MountPath: "/var/run/secrets/google/token",
			},
			*serviceAccountVolumeMount,
		},
	})

	// add GCP token volume to pod
	log.Info("handleGCPVault:applyConfig", "Volume", gcpVolName)
	injectVolume(pod, corev1.Volume{
		Name: gcpVolName,
		VolumeSource: corev1.VolumeSource{
			EmptyDir: &corev1.EmptyDirVolumeSource{
				Medium: corev1.StorageMediumMemory,
			},
		},
	})

	// inject volume mount for all pod containers
	log.Info("handleGCPVault:applyConfig", "VolumeMount", gcpVolName)
	injectVolumeMount(pod, corev1.VolumeMount{
		Name:      gcpVolName,
		ReadOnly:  false,
		MountPath: "/var/run/secrets/google/token",
	})

	// inject app credential env var for all pod containers
	log.Info("handleGCPVault:applyConfig", "EnvVar", "GOOGLE_APPLICATION_CREDENTIALS")
	injectEnvVar(pod, corev1.EnvVar{
		Name:  "GOOGLE_APPLICATION_CREDENTIALS",
		Value: "/var/run/secrets/google/token/key.json",
	})

	return nil
}