github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/cloud/gke/vault/vault_backend.go (about) 1 package vault 2 3 import ( 4 "fmt" 5 6 "github.com/olli-ai/jx/v2/pkg/kube" 7 8 "github.com/jenkins-x/jx-logging/pkg/log" 9 "github.com/olli-ai/jx/v2/pkg/cloud/gke" 10 "github.com/olli-ai/jx/v2/pkg/util" 11 "github.com/pkg/errors" 12 "k8s.io/client-go/kubernetes" 13 ) 14 15 const ( 16 gkeServiceAccountSecretKey = "service-account.json" 17 //DefaultVaultAbbreviation is vault service accounts suffix 18 DefaultVaultAbbreviation = "vt" 19 ) 20 21 var ( 22 ServiceAccountRoles = []string{"roles/storage.objectAdmin", 23 "roles/cloudkms.admin", 24 "roles/cloudkms.cryptoKeyEncrypterDecrypter", 25 } 26 ) 27 28 // KmsConfig keeps the configuration for Google KMS service 29 type KmsConfig struct { 30 Keyring string 31 Key string 32 Location string 33 project string 34 } 35 36 // This is a loose collection of methods needed to set up a vault in GKE. 37 // If they are generic enough and needed elsewhere, we can move them up one level to more generic GCP methods. 38 39 // CreateKmsConfig creates a KMS config for the GKE Vault 40 func CreateKmsConfig(gcloud gke.GClouder, vaultName, keyringName string, keyName string, projectID string) (*KmsConfig, error) { 41 if keyringName == "" { 42 keyringName = gke.KeyringName(vaultName) 43 } 44 config := &KmsConfig{ 45 Keyring: keyringName, 46 Key: keyName, 47 Location: gke.KmsLocation, 48 project: projectID, 49 } 50 51 err := gcloud.CreateKmsKeyring(config.Keyring, config.project) 52 if err != nil { 53 return nil, errors.Wrapf(err, "creating kms keyring '%s'", config.Keyring) 54 } 55 56 if config.Key == "" { 57 config.Key = gke.KeyName(vaultName) 58 } 59 60 err = gcloud.CreateKmsKey(config.Key, config.Keyring, config.project) 61 if err != nil { 62 return nil, errors.Wrapf(err, "creating the kms key '%s'", config.Key) 63 } 64 return config, nil 65 } 66 67 // CreateGCPServiceAccount creates a service account in GCP for the vault service 68 func CreateVaultGCPServiceAccount(gcloud gke.GClouder, kubeClient kubernetes.Interface, vaultName, namespace, clusterName, projectID string) (string, error) { 69 70 gcpServiceAccountSecretName, error := gcloud.CreateGCPServiceAccount(kubeClient, vaultName, DefaultVaultAbbreviation, namespace, clusterName, projectID, ServiceAccountRoles, gkeServiceAccountSecretKey) 71 72 if error != nil { 73 return "", errors.Wrap(error, "creating the Vault GCP Service Account") 74 } 75 return gcpServiceAccountSecretName, nil 76 } 77 78 // CreateBucket Creates a bucket in GKE to store the backend (encrypted) data for vault 79 func CreateBucket(gcloud gke.GClouder, vaultName, bucketName string, projectID, zone string, recreate bool, batchMode bool, handles util.IOFileHandles) (string, error) { 80 if bucketName == "" { 81 bucketName = gke.BucketName(vaultName) 82 } 83 exists, err := gcloud.BucketExists(projectID, bucketName) 84 if err != nil { 85 return "", errors.Wrap(err, "checking if Vault GCS bucket exists") 86 } 87 if exists { 88 if !recreate { 89 return bucketName, nil 90 } 91 if batchMode { 92 log.Logger().Warnf("We are deleting the Vault bucket %s so that Vault will install cleanly", bucketName) 93 } else { 94 if answer, err := util.Confirm(fmt.Sprintf("We are about to delete bucket %q, so we can install a clean Vault. Are you sure: ", bucketName), 95 true, "We recommend you delete the Vault bucket on install to ensure Vault starts up reliably", handles); !answer { 96 return bucketName, err 97 } 98 } 99 err = gcloud.DeleteAllObjectsInBucket(bucketName) 100 if err != nil { 101 return "", errors.Wrapf(err, "failed to remove objects from GCS bucket %s", bucketName) 102 } 103 } 104 105 if zone == "" { 106 return "", errors.New("GKE zone must be provided in 'gke-zone' option") 107 } 108 region := gke.GetRegionFromZone(zone) 109 err = gcloud.CreateBucket(projectID, bucketName, region) 110 if err != nil { 111 return "", errors.Wrap(err, "creating Vault GCS bucket") 112 } 113 return bucketName, nil 114 } 115 116 // GetGoogleZone returns the Google zone as registered in the install values during the Jenkins X install process. 117 // If the zone cannot be read the empty string is returned. 118 func GetGoogleZone(kubeClient kubernetes.Interface, ns string) string { 119 data, err := kube.ReadInstallValues(kubeClient, ns) 120 if err != nil { 121 return "" 122 } 123 return data[kube.Zone] 124 } 125 126 // GetGoogleProjectID returns the Google project ID as registered in the install values during the Jenkins X install process. 127 // If the project ID cannot be read the empty string is returned. 128 func GetGoogleProjectID(kubeClient kubernetes.Interface, ns string) string { 129 data, err := kube.ReadInstallValues(kubeClient, ns) 130 if err != nil { 131 return "" 132 } 133 return data[kube.ProjectID] 134 }