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
}