From fb6cf45a2fcd83a69bd3b6bfb98a7c40a1251a8c Mon Sep 17 00:00:00 2001 From: srinandan <13950006+srinandan@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:16:28 -0700 Subject: [PATCH 1/5] feat: adds feature to provision app integration #137 --- cmd/provision/provision.go | 83 ++++++++++++++++++++++++++ cmd/root.go | 2 + internal/client/provision/provision.go | 55 +++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 cmd/provision/provision.go create mode 100644 internal/client/provision/provision.go diff --git a/cmd/provision/provision.go b/cmd/provision/provision.go new file mode 100644 index 00000000..63a75ac1 --- /dev/null +++ b/cmd/provision/provision.go @@ -0,0 +1,83 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package provision + +import ( + "fmt" + "internal/apiclient" + "internal/client/provision" + "regexp" + + "github.com/spf13/cobra" +) + +// Cmd to provision App Integration +var Cmd = &cobra.Command{ + Use: "provision", + Short: "Provisions application integration", + Long: "Provisions application integration in the region", + Args: func(cmd *cobra.Command, args []string) (err error) { + cmdProject := cmd.Flag("proj") + cmdRegion := cmd.Flag("reg") + if err = apiclient.SetRegion(cmdRegion.Value.String()); err != nil { + return err + } + return apiclient.SetProjectID(cmdProject.Value.String()) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + cloudKMS := cmd.Flag("cloudkms").Value.String() + serviceAccount := cmd.Flag("service-account").Value.String() + + if cloudKMS != "" { + re := regexp.MustCompile(`locations\/([a-zA-Z0-9_-]+)\/keyRings\/([a-zA-Z0-9_-]+)\/cryptoKeys\/([a-zA-Z0-9_-]+)`) + ok := re.Match([]byte(cloudKMS)) + if !ok { + return fmt.Errorf("CloudKMS key must be of the format " + + "locations/{location}/keyRings/{test}/cryptoKeys/{cryptoKey}") + } + } + + if serviceAccount != "" { + re := regexp.MustCompile(`[a-zA-Z0-9-]+@[a-zA-Z0-9-]+\.iam\.gserviceaccount\.com`) + ok := re.Match([]byte(serviceAccount)) + if !ok { + return fmt.Errorf("service account must of the format " + + "@.iam.gserviceaccount.com") + } + } + + _, err = provision.Provision(cloudKMS, samples, gmek, serviceAccount) + return err + }, +} + +var samples, gmek bool + +func init() { + var cloudKMS, serviceAccount, project, region string + + Cmd.PersistentFlags().StringVarP(&project, "proj", "p", + "", "Integration GCP Project name") + Cmd.PersistentFlags().StringVarP(®ion, "reg", "r", + "", "Integration region name") + Cmd.Flags().StringVarP(&cloudKMS, "cloudkms", "k", + "", "Cloud KMS config for AuthModule to encrypt/decrypt credentials") + Cmd.Flags().BoolVarP(&samples, "samples", "s", + true, "Indicates if sample workflow should be created along with provisioning") + Cmd.Flags().BoolVarP(&gmek, "gmek", "g", + true, "Indicates provision with GMEK or CMEK") + Cmd.Flags().StringVarP(&serviceAccount, "service-account", "", + "", "User input run-as service account") +} diff --git a/cmd/root.go b/cmd/root.go index 5c48d40e..da2e7511 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -29,6 +29,7 @@ import ( "github.com/GoogleCloudPlatform/application-integration-management-toolkit/cmd/endpoints" "github.com/GoogleCloudPlatform/application-integration-management-toolkit/cmd/integrations" "github.com/GoogleCloudPlatform/application-integration-management-toolkit/cmd/preferences" + "github.com/GoogleCloudPlatform/application-integration-management-toolkit/cmd/provision" "github.com/GoogleCloudPlatform/application-integration-management-toolkit/cmd/sfdcchannels" "github.com/GoogleCloudPlatform/application-integration-management-toolkit/cmd/sfdcinstances" "github.com/GoogleCloudPlatform/application-integration-management-toolkit/cmd/token" @@ -142,6 +143,7 @@ func init() { RootCmd.AddCommand(sfdcinstances.Cmd) RootCmd.AddCommand(sfdcchannels.Cmd) RootCmd.AddCommand(endpoints.Cmd) + RootCmd.AddCommand(provision.Cmd) } func initConfig() { diff --git a/internal/client/provision/provision.go b/internal/client/provision/provision.go new file mode 100644 index 00000000..008cfbf8 --- /dev/null +++ b/internal/client/provision/provision.go @@ -0,0 +1,55 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package provision + +import ( + "fmt" + "internal/apiclient" + "net/url" + "path" + "strconv" + "strings" +) + +// Provision +func Provision(cloudkms string, samples bool, gmek bool, serviceAccount string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.GetBaseIntegrationURL()) + provStr := []string{} + + if serviceAccount != "" { + provStr = append(provStr, "\"runAsServiceAccount\":\""+serviceAccount+"\"") + } + + if cloudkms != "" { + kmsConfig := getCloudKMSConfig(cloudkms) + provStr = append(provStr, "\"cloudKmsConfig\":"+kmsConfig) + } + + provStr = append(provStr, "\"createSampleWorkflows\":"+strconv.FormatBool(samples)) + provStr = append(provStr, "\"provisionGmek\":"+strconv.FormatBool(gmek)) + + u.Path = path.Join(u.Path, "client:provision") + + payload := "{" + strings.Join(provStr, ",") + "}" + fmt.Println(payload) + respBody, err = apiclient.HttpClient(u.String(), payload) + return respBody, err +} + +func getCloudKMSConfig(cloudkms string) string { + kmsParts := strings.Split(cloudkms, "/") + return fmt.Sprintf("{\"kmsLocation\":\"%s\",\"kmsRing\":\"%s\",\"key\":\"%s\",\"keyVersion\":\"%s\",\"kmsProjectId\":\"%s\"}", + kmsParts[3], kmsParts[5], kmsParts[7], kmsParts[9], kmsParts[1]) +} From 0e5e6ff39081f05f1ce61a1f6559419a25f8e5d0 Mon Sep 17 00:00:00 2001 From: srinandan <13950006+srinandan@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:19:15 -0700 Subject: [PATCH 2/5] chore: fix linting errors #137 --- cmd/provision/provision.go | 3 ++- internal/client/integrations/integrations.go | 2 -- internal/client/provision/provision.go | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cmd/provision/provision.go b/cmd/provision/provision.go index 63a75ac1..1544c425 100644 --- a/cmd/provision/provision.go +++ b/cmd/provision/provision.go @@ -16,9 +16,10 @@ package provision import ( "fmt" + "regexp" + "internal/apiclient" "internal/client/provision" - "regexp" "github.com/spf13/cobra" ) diff --git a/internal/client/integrations/integrations.go b/internal/client/integrations/integrations.go index 97dc33c7..51c17a12 100644 --- a/internal/client/integrations/integrations.go +++ b/internal/client/integrations/integrations.go @@ -757,7 +757,6 @@ func GetSfdcInstances(integration []byte) (instances map[string]string, err erro // GetConnections func GetConnections(integration []byte) (connections []string, err error) { - iversion := integrationVersion{} err = json.Unmarshal(integration, &iversion) @@ -779,7 +778,6 @@ func GetConnections(integration []byte) (connections []string, err error) { // GetConnectionsWithRegion func GetConnectionsWithRegion(integration []byte) (connections []integrationConnection, err error) { - iversion := integrationVersion{} err = json.Unmarshal(integration, &iversion) diff --git a/internal/client/provision/provision.go b/internal/client/provision/provision.go index 008cfbf8..50cf37f9 100644 --- a/internal/client/provision/provision.go +++ b/internal/client/provision/provision.go @@ -16,11 +16,12 @@ package provision import ( "fmt" - "internal/apiclient" "net/url" "path" "strconv" "strings" + + "internal/apiclient" ) // Provision @@ -43,7 +44,6 @@ func Provision(cloudkms string, samples bool, gmek bool, serviceAccount string) u.Path = path.Join(u.Path, "client:provision") payload := "{" + strings.Join(provStr, ",") + "}" - fmt.Println(payload) respBody, err = apiclient.HttpClient(u.String(), payload) return respBody, err } From 262ef6251df0f2b70cbf70806179a8809e49b0d1 Mon Sep 17 00:00:00 2001 From: srinandan <13950006+srinandan@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:55:36 -0700 Subject: [PATCH 3/5] bug: fixes regex for cloudkms #137 --- cmd/provision/provision.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/provision/provision.go b/cmd/provision/provision.go index 1544c425..98860d28 100644 --- a/cmd/provision/provision.go +++ b/cmd/provision/provision.go @@ -42,11 +42,11 @@ var Cmd = &cobra.Command{ serviceAccount := cmd.Flag("service-account").Value.String() if cloudKMS != "" { - re := regexp.MustCompile(`locations\/([a-zA-Z0-9_-]+)\/keyRings\/([a-zA-Z0-9_-]+)\/cryptoKeys\/([a-zA-Z0-9_-]+)`) + re := regexp.MustCompile(`projects\/([a-zA-Z0-9_-]+)\/locations\/([a-zA-Z0-9_-]+)\/keyRings\/([a-zA-Z0-9_-]+)\/cryptoKeys\/([a-zA-Z0-9_-]+)\/cryptoKeyVersions\/([0-9]+)`) ok := re.Match([]byte(cloudKMS)) if !ok { return fmt.Errorf("CloudKMS key must be of the format " + - "locations/{location}/keyRings/{test}/cryptoKeys/{cryptoKey}") + "projects/{project}/locations/{location}/keyRings/{test}/cryptoKeys/{cryptoKey}/cryptoKeyVersions/{cryptoKeyVersion}") } } From dd1b2a453d56b2edcadfce51a89daf4215c31852 Mon Sep 17 00:00:00 2001 From: srinandan <13950006+srinandan@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:57:38 -0700 Subject: [PATCH 4/5] bug: fixes typo in error msg #137 --- cmd/provision/provision.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/provision/provision.go b/cmd/provision/provision.go index 98860d28..950b91ee 100644 --- a/cmd/provision/provision.go +++ b/cmd/provision/provision.go @@ -46,7 +46,7 @@ var Cmd = &cobra.Command{ ok := re.Match([]byte(cloudKMS)) if !ok { return fmt.Errorf("CloudKMS key must be of the format " + - "projects/{project}/locations/{location}/keyRings/{test}/cryptoKeys/{cryptoKey}/cryptoKeyVersions/{cryptoKeyVersion}") + "projects/{project}/locations/{location}/keyRings/{keyRing}/cryptoKeys/{cryptoKey}/cryptoKeyVersions/{cryptoKeyVersion}") } } From 28f89701391c321df163d0680d09bfaa092742d8 Mon Sep 17 00:00:00 2001 From: srinandan <13950006+srinandan@users.noreply.github.com> Date: Tue, 3 Oct 2023 11:02:12 -0700 Subject: [PATCH 5/5] chore: fix linting errors #137 --- cmd/provision/provision.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/provision/provision.go b/cmd/provision/provision.go index 950b91ee..a70b4090 100644 --- a/cmd/provision/provision.go +++ b/cmd/provision/provision.go @@ -42,11 +42,13 @@ var Cmd = &cobra.Command{ serviceAccount := cmd.Flag("service-account").Value.String() if cloudKMS != "" { - re := regexp.MustCompile(`projects\/([a-zA-Z0-9_-]+)\/locations\/([a-zA-Z0-9_-]+)\/keyRings\/([a-zA-Z0-9_-]+)\/cryptoKeys\/([a-zA-Z0-9_-]+)\/cryptoKeyVersions\/([0-9]+)`) + re := regexp.MustCompile(`projects\/([a-zA-Z0-9_-]+)\/locations\/([a-zA-Z0-9_-]+)\/` + + `keyRings\/([a-zA-Z0-9_-]+)\/cryptoKeys\/([a-zA-Z0-9_-]+)\/cryptoKeyVersions\/([0-9]+)`) ok := re.Match([]byte(cloudKMS)) if !ok { return fmt.Errorf("CloudKMS key must be of the format " + - "projects/{project}/locations/{location}/keyRings/{keyRing}/cryptoKeys/{cryptoKey}/cryptoKeyVersions/{cryptoKeyVersion}") + "projects/{project}/locations/{location}/keyRings/{keyRing}/cryptoKeys/{cryptoKey}" + + "/cryptoKeyVersions/{cryptoKeyVersion}") } }