func create()

in internal/client/connections/connectors.go [311:725]


func create(name string, content []byte, serviceAccountName string, serviceAccountProject string,
	encryptionKey string, grantPermission bool, createSecret bool,
) (respBody []byte, err error) {
	var secretVersion string

	c := connectionRequest{}
	if err = json.Unmarshal(content, &c); err != nil {
		return nil, err
	}

	// service account overrides have been provided, use them
	if serviceAccountName != "" {
		// set the project id if one was not presented
		if serviceAccountProject == "" {
			serviceAccountProject = apiclient.GetProjectID()
		}
		serviceAccountName = fmt.Sprintf("%s@%s.iam.gserviceaccount.com", serviceAccountName, serviceAccountProject)
		// create the SA if it doesn't exist
		if err = apiclient.CreateServiceAccount(serviceAccountName); err != nil {
			return nil, err
		}
	} else if grantPermission { // use the default compute engine SA to grant permissions
		serviceAccountName, err = apiclient.GetComputeEngineDefaultServiceAccount(apiclient.GetProjectID())
		if err != nil {
			return nil, err
		}
	}

	if c.ServiceAccount == nil && serviceAccountName != "" {
		c.ServiceAccount = new(string)
		*c.ServiceAccount = serviceAccountName
	}

	if c.ConnectorDetails == nil {
		return nil, fmt.Errorf("connectorDetails must be set." +
			" See https://github.com/GoogleCloudPlatform/application-integration-management-toolkit" +
			"#connectors-for-third-party-applications for more details")
	}

	if c.ConnectorDetails.Version != nil && c.ConnectorDetails.VersionId != nil {
		return nil, fmt.Errorf("Version and VersionId cannot be set")
	}

	if c.ConnectorDetails.Name == "" || c.ConnectorDetails.Provider == "" {
		return nil, fmt.Errorf("connectorDetails Name and Provider must be set." +
			" See https://github.com/GoogleCloudPlatform/application-integration-management-toolkit" +
			"#connectors-for-third-party-applications for more details")
	}

	if c.ConnectorDetails.Provider == "customconnector" && c.ConnectorDetails.VersionId == nil {
		return nil, fmt.Errorf("connectorDetails VersionId must be set for customconnectors")
	} else if c.ConnectorDetails.Provider != "customconnector" && c.ConnectorDetails.Version == nil {
		return nil, fmt.Errorf("connectorDetails Version must be set")
	}

	// handle project id & region overrides
	if c.ConfigVariables != nil && len(*c.ConfigVariables) > 0 {
		for index := range *c.ConfigVariables {
			if (*c.ConfigVariables)[index].Key == "project_id" && *(*c.ConfigVariables)[index].StringValue == "$PROJECT_ID$" {
				*(*c.ConfigVariables)[index].StringValue = apiclient.GetProjectID()
			} else if strings.Contains((*c.ConfigVariables)[index].Key, "_region") &&
				*(*c.ConfigVariables)[index].StringValue == "$REGION$" {
				*(*c.ConfigVariables)[index].StringValue = apiclient.GetRegion()
			}
		}
	}

	// check if permissions need to be set
	if grantPermission && c.ServiceAccount != nil {
		var projectID string

		switch c.ConnectorDetails.Name {
		case "pubsub":
			var topicName string

			for _, configVar := range *c.ConfigVariables {
				if configVar.Key == "project_id" {
					projectID = *configVar.StringValue
				}
				if configVar.Key == "topic_id" {
					topicName = *configVar.StringValue
				}
			}

			if projectID == "" || topicName == "" {
				return nil, fmt.Errorf("projectId or topicName was not set")
			}

			if err = apiclient.SetPubSubIAMPermission(projectID, topicName, *c.ServiceAccount); err != nil {
				clilog.Warning.Printf("Unable to update permissions for the service account: %v\n", err)
			}
		case "bigquery":
			var datasetID string

			for _, configVar := range *c.ConfigVariables {
				if configVar.Key == "project_id" {
					projectID = *configVar.StringValue
				}
				if configVar.Key == "dataset_id" {
					datasetID = *configVar.StringValue
				}
			}
			if projectID == "" || datasetID == "" {
				return nil, fmt.Errorf("project_id or dataset_id was not set")
			}

			if err = apiclient.SetBigQueryIAMPermission(projectID, datasetID, *c.ServiceAccount); err != nil {
				clilog.Warning.Printf("Unable to update permissions for the service account: %v\n", err)
			}
		case "gcs":
			for _, configVar := range *c.ConfigVariables {
				if configVar.Key == "project_id" {
					projectID = *configVar.StringValue
				}
			}
			if projectID == "" {
				return nil, fmt.Errorf("project_id was not set")
			}
			if err = apiclient.SetCloudStorageIAMPermission(projectID, *c.ServiceAccount); err != nil {
				clilog.Warning.Printf("Unable to update permissions for the service account: %v\n", err)
			}
		case "cloudsql-mysql", "cloudsql-postgresql", "cloudsql-sqlserver":
			for _, configVar := range *c.ConfigVariables {
				if configVar.Key == "project_id" {
					projectID = *configVar.StringValue
				}
			}
			if projectID == "" {
				return nil, fmt.Errorf("projectId was not set")
			}
			if err = apiclient.SetCloudSQLIAMPermission(projectID, *c.ServiceAccount); err != nil {
				clilog.Warning.Printf("Unable to update permissions for the service account: %v\n", err)
			}
		case "cloudspanner":
			for _, configVar := range *c.ConfigVariables {
				if configVar.Key == "project_id" {
					projectID = *configVar.StringValue
				}
			}
			if projectID == "" {
				return nil, fmt.Errorf("project_id was not set")
			}
			if err = apiclient.SetCloudSpannerIAMPermission(projectID, *c.ServiceAccount); err != nil {
				clilog.Warning.Printf("Unable to update permissions for the service account: %v\n", err)
			}
		}
	}

	c.ConnectorVersion = new(string)
	if c.ConnectorDetails.VersionId != nil {
		*c.ConnectorVersion = fmt.Sprintf("projects/%s/locations/global/providers/%s/connectors/%s/versions/%s",
			apiclient.GetProjectID(), c.ConnectorDetails.Provider, c.ConnectorDetails.Name, *c.ConnectorDetails.VersionId)
	} else {
		*c.ConnectorVersion = fmt.Sprintf("projects/%s/locations/global/providers/%s/connectors/%s/versions/%d",
			apiclient.GetProjectID(), c.ConnectorDetails.Provider, c.ConnectorDetails.Name, *c.ConnectorDetails.Version)
	}

	// remove the element
	c.ConnectorDetails = nil

	// handle secrets for username
	if c.AuthConfig != nil {
		switch c.AuthConfig.AuthType {
		case "USER_PASSWORD":
			if c.AuthConfig.UserPassword != nil && c.AuthConfig.UserPassword.PasswordDetails != nil {
				if createSecret {
					if c.AuthConfig.UserPassword.PasswordDetails.Reference == "" {
						return nil, fmt.Errorf("create-secret is enabled, but reference is not passed")
					}
					payload, err := readSecretFile(c.AuthConfig.UserPassword.PasswordDetails.Reference)
					if err != nil {
						return nil, err
					}

					// check if a Cloud KMS key was passsed, assume the file is encrypted
					if encryptionKey != "" {
						encryptionKey := path.Join("projects", apiclient.GetProjectID(), encryptionKey)
						payload, err = cloudkms.DecryptSymmetric(encryptionKey, payload)
						if err != nil {
							return nil, err
						}
					}

					if secretVersion, err = secmgr.Create(
						apiclient.GetProjectID(),
						c.AuthConfig.UserPassword.PasswordDetails.SecretName,
						payload); err != nil {
						return nil, err
					}

					secretName := c.AuthConfig.UserPassword.PasswordDetails.SecretName
					c.AuthConfig.UserPassword.Password = new(secret)
					c.AuthConfig.UserPassword.Password.SecretVersion = secretVersion
					c.AuthConfig.UserPassword.PasswordDetails = nil // clean the input
					if grantPermission && c.ServiceAccount != nil {
						// grant connector service account access to secretVersion
						if err = apiclient.SetSecretManagerIAMPermission(
							apiclient.GetProjectID(),
							secretName,
							*c.ServiceAccount); err != nil {
							return nil, err
						}
					}
				} else {
					c.AuthConfig.UserPassword.Password = new(secret)
					c.AuthConfig.UserPassword.Password.SecretVersion = fmt.Sprintf("projects/%s/secrets/%s/versions/1",
						apiclient.GetProjectID(), c.AuthConfig.UserPassword.PasswordDetails.SecretName)
					c.AuthConfig.UserPassword.PasswordDetails = nil // clean the input
				}
			}
		case "OAUTH2_JWT_BEARER":
			if c.AuthConfig.Oauth2JwtBearer != nil && c.AuthConfig.Oauth2JwtBearer.ClientKeyDetails != nil {
				if createSecret {
					clilog.Warning.Printf("Creating secrets for %s is not implemented\n", c.AuthConfig.AuthType)
					payload, err := readSecretFile(c.AuthConfig.Oauth2JwtBearer.ClientKeyDetails.Reference)
					if err != nil {
						return nil, err
					}
					// check if a Cloud KMS key was passsed, assume the file is encrypted
					if encryptionKey != "" {
						encryptionKey := path.Join("projects", apiclient.GetProjectID(), encryptionKey)
						payload, err = cloudkms.DecryptSymmetric(encryptionKey, payload)
						if err != nil {
							return nil, err
						}
					}
					if secretVersion, err = secmgr.Create(
						apiclient.GetProjectID(),
						c.AuthConfig.Oauth2JwtBearer.ClientKeyDetails.SecretName,
						payload); err != nil {
						return nil, err
					}
					secretName := c.AuthConfig.Oauth2JwtBearer.ClientKeyDetails.SecretName
					c.AuthConfig.Oauth2JwtBearer.ClientKey = new(secret)
					c.AuthConfig.Oauth2JwtBearer.ClientKey.SecretVersion = secretVersion
					c.AuthConfig.Oauth2JwtBearer.ClientKeyDetails = nil // clean the input
					if grantPermission && c.ServiceAccount != nil {
						// grant connector service account access to secret version
						if err = apiclient.SetSecretManagerIAMPermission(
							apiclient.GetProjectID(),
							secretName,
							*c.ServiceAccount); err != nil {
							return nil, err
						}
					}
				} else {
					c.AuthConfig.Oauth2JwtBearer.ClientKey = new(secret)
					c.AuthConfig.Oauth2JwtBearer.ClientKey.SecretVersion = fmt.Sprintf("projects/%s/secrets/%s/versions/1",
						apiclient.GetProjectID(),
						c.AuthConfig.Oauth2JwtBearer.ClientKeyDetails.SecretName)
					c.AuthConfig.Oauth2JwtBearer.ClientKeyDetails = nil
				}
			}
		case "OAUTH2_CLIENT_CREDENTIALS":
			if createSecret {
				clilog.Warning.Printf("Creating secrets for %s is not implemented\n", c.AuthConfig.AuthType)
			}
		case "SSH_PUBLIC_KEY":
			if createSecret {
				clilog.Warning.Printf("Creating secrets for %s is not implemented\n", c.AuthConfig.AuthType)
			}
		case "OAUTH2_AUTH_CODE_FLOW":
			if createSecret {
				clilog.Warning.Printf("Creating secrets for %s is not implemented\n", c.AuthConfig.AuthType)
			}
		default:
			clilog.Warning.Printf("No auth type found, assuming service account auth\n")
		}
	}

	// handle secrets for ssl config
	if c.SslConfig != nil {
		if c.SslConfig.PrivateServerCertificate != nil && c.SslConfig.PrivateServerCertificate.SecretDetails != nil {
			if createSecret {
				payload, err := readSecretFile(c.SslConfig.PrivateServerCertificate.SecretDetails.Reference)
				if err != nil {
					return nil, err
				}
				// check if a Cloud KMS key was passsed, assume the file is encrypted
				if encryptionKey != "" {
					encryptionKey := path.Join("projects", apiclient.GetProjectID(), encryptionKey)
					payload, err = cloudkms.DecryptSymmetric(encryptionKey, payload)
					if err != nil {
						return nil, err
					}
				}

				if secretVersion, err = secmgr.Create(
					apiclient.GetProjectID(),
					c.SslConfig.PrivateServerCertificate.SecretDetails.SecretName,
					payload); err != nil {
					return nil, err
				}

				c.SslConfig.PrivateServerCertificate.SecretVersion = new(string)
				*c.SslConfig.PrivateServerCertificate.SecretVersion = secretVersion
				c.SslConfig.PrivateServerCertificate.SecretDetails = nil // clean the input

			} else {
				c.SslConfig.PrivateServerCertificate.SecretVersion = new(string)
				*c.SslConfig.PrivateServerCertificate.SecretVersion = fmt.Sprintf("projects/%s/secrets/%s/versions/1",
					apiclient.GetProjectID(), c.SslConfig.PrivateServerCertificate.SecretDetails.SecretName)
				c.SslConfig.PrivateServerCertificate.SecretDetails = nil // clean the input
			}
		}
		if c.SslConfig.ClientCertificate != nil && c.SslConfig.ClientCertificate.SecretDetails != nil {
			if createSecret {
				payload, err := readSecretFile(c.SslConfig.ClientCertificate.SecretDetails.Reference)
				if err != nil {
					return nil, err
				}
				// check if a Cloud KMS key was passsed, assume the file is encrypted
				if encryptionKey != "" {
					encryptionKey := path.Join("projects", apiclient.GetProjectID(), encryptionKey)
					payload, err = cloudkms.DecryptSymmetric(encryptionKey, payload)
					if err != nil {
						return nil, err
					}
				}

				if secretVersion, err = secmgr.Create(
					apiclient.GetProjectID(),
					c.SslConfig.ClientCertificate.SecretDetails.SecretName,
					payload); err != nil {
					return nil, err
				}

				c.SslConfig.ClientCertificate.SecretVersion = new(string)
				*c.SslConfig.ClientCertificate.SecretVersion = secretVersion
				c.SslConfig.ClientCertificate.SecretDetails = nil // clean the input
			} else {
				c.SslConfig.ClientCertificate.SecretVersion = new(string)
				*c.SslConfig.ClientCertificate.SecretVersion = fmt.Sprintf("projects/%s/secrets/%s/versions/1",
					apiclient.GetProjectID(), c.SslConfig.ClientCertificate.SecretDetails.SecretName)
				c.SslConfig.ClientCertificate.SecretDetails = nil // clean the input
			}
		}
		if c.SslConfig.ClientPrivateKey != nil && c.SslConfig.ClientPrivateKey.SecretDetails != nil {
			if createSecret {
				payload, err := readSecretFile(c.SslConfig.ClientPrivateKey.SecretDetails.Reference)
				if err != nil {
					return nil, err
				}
				// check if a Cloud KMS key was passsed, assume the file is encrypted
				if encryptionKey != "" {
					encryptionKey := path.Join("projects", apiclient.GetProjectID(), encryptionKey)
					payload, err = cloudkms.DecryptSymmetric(encryptionKey, payload)
					if err != nil {
						return nil, err
					}
				}

				if secretVersion, err = secmgr.Create(
					apiclient.GetProjectID(),
					c.SslConfig.ClientPrivateKey.SecretDetails.SecretName,
					payload); err != nil {
					return nil, err
				}

				c.SslConfig.ClientPrivateKey.SecretVersion = new(string)
				*c.SslConfig.ClientPrivateKey.SecretVersion = secretVersion
				c.SslConfig.ClientPrivateKey.SecretDetails = nil // clean the input
			} else {
				c.SslConfig.ClientPrivateKey.SecretVersion = new(string)
				*c.SslConfig.ClientPrivateKey.SecretVersion = fmt.Sprintf("projects/%s/secrets/%s/versions/1",
					apiclient.GetProjectID(), c.SslConfig.ClientPrivateKey.SecretDetails.SecretName)
				c.SslConfig.ClientPrivateKey.SecretDetails = nil // clean the input
			}
		}
		if c.SslConfig.ClientPrivateKeyPass != nil && c.SslConfig.ClientPrivateKeyPass.SecretDetails != nil {
			if createSecret {
				payload, err := readSecretFile(c.SslConfig.ClientPrivateKeyPass.SecretDetails.Reference)
				if err != nil {
					return nil, err
				}
				// check if a Cloud KMS key was passsed, assume the file is encrypted
				if encryptionKey != "" {
					encryptionKey := path.Join("projects", apiclient.GetProjectID(), encryptionKey)
					payload, err = cloudkms.DecryptSymmetric(encryptionKey, payload)
					if err != nil {
						return nil, err
					}
				}

				if secretVersion, err = secmgr.Create(
					apiclient.GetProjectID(),
					c.SslConfig.ClientPrivateKeyPass.SecretDetails.SecretName,
					payload); err != nil {
					return nil, err
				}

				c.SslConfig.ClientPrivateKeyPass.SecretVersion = new(string)
				*c.SslConfig.ClientPrivateKeyPass.SecretVersion = secretVersion
				c.SslConfig.ClientPrivateKeyPass.SecretDetails = nil // clean the input
			} else {
				c.SslConfig.ClientPrivateKeyPass.SecretVersion = new(string)
				*c.SslConfig.ClientPrivateKeyPass.SecretVersion = fmt.Sprintf("projects/%s/secrets/%s/versions/1",
					apiclient.GetProjectID(), c.SslConfig.ClientPrivateKeyPass.SecretDetails.SecretName)
				c.SslConfig.ClientPrivateKeyPass.SecretDetails = nil // clean the input
			}
		}
	}

	u, _ := url.Parse(apiclient.GetBaseConnectorURL())
	q := u.Query()
	q.Set("connectionId", name)
	u.RawQuery = q.Encode()

	if content, err = json.Marshal(c); err != nil {
		return nil, err
	}

	respBody, err = apiclient.HttpClient(u.String(), string(content))
	return respBody, err
}