diff --git a/cmd/apicategories/apicategories.go b/cmd/apicategories/apicategories.go new file mode 100644 index 000000000..35ea60101 --- /dev/null +++ b/cmd/apicategories/apicategories.go @@ -0,0 +1,43 @@ +// 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 apicategories + +import ( + "github.com/spf13/cobra" +) + +// Cmd to manage api catalog items +var Cmd = &cobra.Command{ + Use: "apicategories", + Short: "Manage Apigee API categories that are tagged on catalog items", + Long: "Manage Apigee API categories that are tagged on catalog items", +} + +var org, siteid, id string + +func init() { + Cmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + Cmd.PersistentFlags().StringVarP(&siteid, "siteid", "s", + "", "Name or siteid of the portal") + + Cmd.AddCommand(ListCmd) + Cmd.AddCommand(GetCmd) + Cmd.AddCommand(DelCmd) + Cmd.AddCommand(CreateCmd) + + _ = Cmd.MarkFlagRequired("org") + _ = Cmd.MarkFlagRequired("siteid") +} diff --git a/cmd/apicategories/create.go b/cmd/apicategories/create.go new file mode 100644 index 000000000..b756d1ce8 --- /dev/null +++ b/cmd/apicategories/create.go @@ -0,0 +1,45 @@ +// 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 apicategories + +import ( + "internal/apiclient" + + "internal/client/apicategories" + + "github.com/spf13/cobra" +) + +// CreateCmd to get a catalog items +var CreateCmd = &cobra.Command{ + Use: "create", + Short: "Creates a new API category", + Long: "Creates a new API category", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = apicategories.Create(siteid, name) + return + }, +} + +var name string + +func init() { + CreateCmd.Flags().StringVarP(&name, "name", "n", + "", "API Category name") + _ = CreateCmd.MarkFlagRequired("name") +} diff --git a/cmd/apicategories/delete.go b/cmd/apicategories/delete.go new file mode 100644 index 000000000..4f50432cf --- /dev/null +++ b/cmd/apicategories/delete.go @@ -0,0 +1,42 @@ +// 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 apicategories + +import ( + "internal/apiclient" + "internal/client/apicategories" + + "github.com/spf13/cobra" +) + +// DelCmd to get a catalog items +var DelCmd = &cobra.Command{ + Use: "delete", + Short: "Deletes an API Category by ID", + Long: "Deletes an API Category by ID", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = apicategories.Delete(siteid, id) + return + }, +} + +func init() { + DelCmd.Flags().StringVarP(&id, "id", "i", + "", "API Category ID") + _ = DelCmd.MarkFlagRequired("id") +} diff --git a/cmd/apicategories/get.go b/cmd/apicategories/get.go new file mode 100644 index 000000000..8fa3e2cdc --- /dev/null +++ b/cmd/apicategories/get.go @@ -0,0 +1,43 @@ +// 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 apicategories + +import ( + "internal/apiclient" + + "internal/client/apicategories" + + "github.com/spf13/cobra" +) + +// GetCmd to get a catalog items +var GetCmd = &cobra.Command{ + Use: "get", + Short: "Gets an API Category by ID", + Long: "Gets an API Category by ID", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = apicategories.Get(siteid, id) + return + }, +} + +func init() { + GetCmd.Flags().StringVarP(&id, "id", "i", + "", "API Category ID") + _ = GetCmd.MarkFlagRequired("id") +} diff --git a/cmd/apicategories/list.go b/cmd/apicategories/list.go new file mode 100644 index 000000000..ffa185611 --- /dev/null +++ b/cmd/apicategories/list.go @@ -0,0 +1,36 @@ +// 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 apicategories + +import ( + "internal/apiclient" + "internal/client/apicategories" + + "github.com/spf13/cobra" +) + +// ListCmd to list apicategories +var ListCmd = &cobra.Command{ + Use: "list", + Short: "Returns the API categories associated with a portal", + Long: "Returns the API categories associated with a portal", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = apicategories.List(siteid) + return + }, +} diff --git a/cmd/apidocs/apidocs.go b/cmd/apidocs/apidocs.go new file mode 100644 index 000000000..4e2826b41 --- /dev/null +++ b/cmd/apidocs/apidocs.go @@ -0,0 +1,45 @@ +// 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 apidocs + +import ( + "github.com/spf13/cobra" +) + +// Cmd to manage apis +var Cmd = &cobra.Command{ + Use: "apidocs", + Short: "Manage Apigee API catalog item through ApiDoc", + Long: "Manage Apigee API catalog item through ApiDoc", +} + +var org, siteid, id, name string + +func init() { + Cmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + Cmd.PersistentFlags().StringVarP(&siteid, "siteid", "s", + "", "Name or siteid of the portal") + + Cmd.AddCommand(ListCmd) + Cmd.AddCommand(GetCmd) + Cmd.AddCommand(DelCmd) + Cmd.AddCommand(DocCmd) + Cmd.AddCommand(CreateCmd) + Cmd.AddCommand(UpdateCmd) + + _ = Cmd.MarkFlagRequired("org") + _ = Cmd.MarkFlagRequired("siteid") +} diff --git a/cmd/apidocs/create.go b/cmd/apidocs/create.go new file mode 100644 index 000000000..1a1cc19dc --- /dev/null +++ b/cmd/apidocs/create.go @@ -0,0 +1,84 @@ +// 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 apidocs + +import ( + "fmt" + "strconv" + + "internal/apiclient" + "internal/client/apidocs" + + "github.com/spf13/cobra" +) + +// CreateCmd to create a catalog items +var CreateCmd = &cobra.Command{ + Use: "create", + Short: "Create a new catalog item", + Long: "Create a new catalog item", + Args: func(cmd *cobra.Command, args []string) (err error) { + _, err = strconv.ParseBool(published) + if err != nil { + return fmt.Errorf("published must be a boolean value: %v", err) + } + _, err = strconv.ParseBool(anonAllowed) + if err != nil { + return fmt.Errorf("allow-anon must be a boolean value: %v", err) + } + + _, err = strconv.ParseBool(requireCallbackUrl) + if err != nil { + return fmt.Errorf("require-callback-url must be a boolean value: %v", err) + } + + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = apidocs.Create(siteid, title, description, published, + anonAllowed, apiProductName, requireCallbackUrl, imageUrl, categoryIds) + return + }, +} + +var ( + title, description, published, anonAllowed, apiProductName string + requireCallbackUrl, imageUrl string + categoryIds []string +) + +func init() { + CreateCmd.Flags().StringVarP(&title, "title", "l", + "", "The user-facing name of the catalog item") + CreateCmd.Flags().StringVarP(&description, "desc", "d", + "", "Description of the catalog item") + CreateCmd.Flags().StringVarP(&published, "published", "p", + "", "Denotes whether the catalog item is published to the portal or is in a draft state") + CreateCmd.Flags().StringVarP(&anonAllowed, "allow-anon", "", + "", "Boolean flag that manages user access to the catalog item") + CreateCmd.Flags().StringVarP(&apiProductName, "api-product", "", + "", "The name field of the associated API product") + CreateCmd.Flags().StringVarP(&requireCallbackUrl, "require-callback-url", "", + "", "Whether a callback URL is required when this catalog item's developer app is created") + CreateCmd.Flags().StringVarP(&imageUrl, "image-url", "", + "", "Location of the image used for the catalog item in the catalog") + + CreateCmd.Flags().StringArrayVarP(&categoryIds, "category-ids", "", + nil, "The IDs of the API categories to which this catalog item belongs") + + _ = CreateCmd.MarkFlagRequired("name") + _ = CreateCmd.MarkFlagRequired("title") + _ = CreateCmd.MarkFlagRequired("apiProductName") +} diff --git a/cmd/apidocs/delete.go b/cmd/apidocs/delete.go new file mode 100644 index 000000000..9edafbc4b --- /dev/null +++ b/cmd/apidocs/delete.go @@ -0,0 +1,42 @@ +// 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 apidocs + +import ( + "internal/apiclient" + "internal/client/apidocs" + + "github.com/spf13/cobra" +) + +// DelCmd to get a catalog items +var DelCmd = &cobra.Command{ + Use: "delete", + Short: "Deletes a catalog item", + Long: "Deletes a catalog item", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = apidocs.Delete(siteid, id) + return + }, +} + +func init() { + DelCmd.Flags().StringVarP(&id, "id", "i", + "", "Catalog ID") + _ = DelCmd.MarkFlagRequired("id") +} diff --git a/cmd/apidocs/docs.go b/cmd/apidocs/docs.go new file mode 100644 index 000000000..e1d029dd8 --- /dev/null +++ b/cmd/apidocs/docs.go @@ -0,0 +1,31 @@ +// 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 apidocs + +import ( + "github.com/spf13/cobra" +) + +// DocCmd to manage apis +var DocCmd = &cobra.Command{ + Use: "documentation", + Short: "Manage the documentation for the specified catalog item", + Long: "Manage the documentation for the specified catalog item", +} + +func init() { + DocCmd.AddCommand(GetDocCmd) + DocCmd.AddCommand(UpdateDocCmd) +} diff --git a/cmd/apidocs/get.go b/cmd/apidocs/get.go new file mode 100644 index 000000000..73ef3cd27 --- /dev/null +++ b/cmd/apidocs/get.go @@ -0,0 +1,42 @@ +// 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 apidocs + +import ( + "internal/apiclient" + "internal/client/apidocs" + + "github.com/spf13/cobra" +) + +// GetCmd to get a catalog items +var GetCmd = &cobra.Command{ + Use: "get", + Short: "Gets a catalog item", + Long: "Gets a catalog item", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = apidocs.Get(siteid, id) + return + }, +} + +func init() { + GetCmd.Flags().StringVarP(&id, "id", "i", + "", "Catalog ID") + _ = GetCmd.MarkFlagRequired("id") +} diff --git a/cmd/apidocs/getdocs.go b/cmd/apidocs/getdocs.go new file mode 100644 index 000000000..49ed51e98 --- /dev/null +++ b/cmd/apidocs/getdocs.go @@ -0,0 +1,42 @@ +// 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 apidocs + +import ( + "internal/apiclient" + "internal/client/apidocs" + + "github.com/spf13/cobra" +) + +// GetDocCmd to get a catalog items +var GetDocCmd = &cobra.Command{ + Use: "get", + Short: "Gets the documentation for the specified catalog item", + Long: "Gets the documentation for the specified catalog item", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = apidocs.GetDocumentation(siteid, id) + return + }, +} + +func init() { + GetDocCmd.Flags().StringVarP(&id, "id", "i", + "", "Catalog ID") + _ = GetDocCmd.MarkFlagRequired("id") +} diff --git a/cmd/apidocs/list.go b/cmd/apidocs/list.go new file mode 100644 index 000000000..38a7f5284 --- /dev/null +++ b/cmd/apidocs/list.go @@ -0,0 +1,36 @@ +// 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 apidocs + +import ( + "internal/apiclient" + "internal/client/apidocs" + + "github.com/spf13/cobra" +) + +// ListCmd to list catalog items +var ListCmd = &cobra.Command{ + Use: "list", + Short: "Returns the catalog items associated with a portal", + Long: "Returns the catalog items associated with a portal", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = apidocs.List(siteid) + return + }, +} diff --git a/cmd/apidocs/update.go b/cmd/apidocs/update.go new file mode 100644 index 000000000..6c37fe3eb --- /dev/null +++ b/cmd/apidocs/update.go @@ -0,0 +1,81 @@ +// 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 apidocs + +import ( + "fmt" + "strconv" + + "internal/apiclient" + "internal/client/apidocs" + + "github.com/spf13/cobra" +) + +// UpdateCmd to create a catalog items +var UpdateCmd = &cobra.Command{ + Use: "update", + Short: "Update an existing catalog item", + Long: "Update an existing catalog item", + Args: func(cmd *cobra.Command, args []string) (err error) { + _, err = strconv.ParseBool(published) + if err != nil { + return fmt.Errorf("published must be a boolean value: %v", err) + } + + _, err = strconv.ParseBool(anonAllowed) + if err != nil { + return fmt.Errorf("allow-anon must be a boolean value: %v", err) + } + + _, err = strconv.ParseBool(requireCallbackUrl) + if err != nil { + return fmt.Errorf("require-callback-url must be a boolean value: %v", err) + } + + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = apidocs.Update(siteid, id, title, description, published, + anonAllowed, apiProductName, requireCallbackUrl, imageUrl, categoryIds) + return + }, +} + +func init() { + UpdateCmd.Flags().StringVarP(&id, "id", "i", + "", "Catalog UUID") + UpdateCmd.Flags().StringVarP(&title, "title", "l", + "", "The user-facing name of the catalog item") + UpdateCmd.Flags().StringVarP(&description, "desc", "d", + "", "Description of the catalog item") + UpdateCmd.Flags().StringVarP(&published, "published", "p", + "", "Denotes whether the catalog item is published to the portal or is in a draft state") + UpdateCmd.Flags().StringVarP(&anonAllowed, "allow-anon", "", + "", "Boolean flag that manages user access to the catalog item") + UpdateCmd.Flags().StringVarP(&apiProductName, "api-product", "", + "", "The name field of the associated API product") + UpdateCmd.Flags().StringVarP(&requireCallbackUrl, "require-callback-url", "", + "", "Whether a callback URL is required when this catalog item's developer app is created") + UpdateCmd.Flags().StringVarP(&imageUrl, "image-url", "", + "", "Location of the image used for the catalog item in the catalog") + + UpdateCmd.Flags().StringArrayVarP(&categoryIds, "category-ids", "", + nil, "The IDs of the API categories to which this catalog item belongs") + + _ = UpdateCmd.MarkFlagRequired("id") + _ = UpdateCmd.MarkFlagRequired("title") + _ = UpdateCmd.MarkFlagRequired("apiProductName") +} diff --git a/cmd/apidocs/updatedocs.go b/cmd/apidocs/updatedocs.go new file mode 100644 index 000000000..525f0b821 --- /dev/null +++ b/cmd/apidocs/updatedocs.go @@ -0,0 +1,94 @@ +// 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 apidocs + +import ( + "encoding/json" + "fmt" + + "internal/apiclient" + "internal/client/apidocs" + + "github.com/apigee/apigeecli/cmd/utils" + "github.com/spf13/cobra" +) + +// UpdateDocCmd to get a catalog items +var UpdateDocCmd = &cobra.Command{ + Use: "update", + Short: "Updates the documentation for the specified catalog item", + Long: "Updates the documentation for the specified catalog item", + Args: func(cmd *cobra.Command, args []string) (err error) { + if openAPIPath == "" && graphQLPath == "" { + return fmt.Errorf("The flags openapi and grapql cannot both be empty") + } + if openAPIPath != "" && graphQLPath != "" { + return fmt.Errorf("The flags openapi and grapql cannot both be set") + } + if graphQLPath != "" && endpointUri == "" { + return fmt.Errorf("The flags graphQLPath and endpointUri must be set together") + } + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + var openAPIDoc, graphQLDoc []byte + var openAPI, graphQL string + + if openAPIPath != "" { + if openAPIDoc, err = utils.ReadFile(openAPIPath); err != nil { + return err + } + if openAPIDoc, err = json.Marshal(openAPIDoc); err != nil { + return err + } + openAPI = string(openAPIDoc) + } + + if graphQLPath != "" { + graphQLDoc, err = utils.ReadFile(graphQLPath) + if err != nil { + return err + } + if graphQLDoc, err = json.Marshal(graphQLDoc); err != nil { + return err + } + graphQL = string(graphQLDoc) + } + + _, err = apidocs.UpdateDocumentation(siteid, id, name, openAPI, graphQL, endpointUri) + return + }, +} + +var ( + openAPIPath, graphQLPath string + endpointUri string +) + +func init() { + UpdateDocCmd.Flags().StringVarP(&id, "id", "i", + "", "Catalog UUID") + UpdateDocCmd.Flags().StringVarP(&name, "name", "n", + "", "Display Name") + UpdateDocCmd.Flags().StringVarP(&openAPIPath, "openapi", "p", + "", "Path to a file containing OpenAPI Specification documentation") + UpdateDocCmd.Flags().StringVarP(&graphQLPath, "graphql", "q", + "", "Path to a file containing GraphQL documentation") + UpdateDocCmd.Flags().StringVarP(&endpointUri, "endpointUri", "e", + "", "URI for the GraphQL proxy") + + _ = UpdateDocCmd.MarkFlagRequired("id") + _ = UpdateDocCmd.MarkFlagRequired("name") +} diff --git a/cmd/datastores/create.go b/cmd/datastores/create.go new file mode 100644 index 000000000..6d95fedbf --- /dev/null +++ b/cmd/datastores/create.go @@ -0,0 +1,64 @@ +// 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 datastores + +import ( + "internal/apiclient" + "internal/client/datastores" + + "github.com/spf13/cobra" +) + +// CreateCmd to create a datastore +var CreateCmd = &cobra.Command{ + Use: "create", + Short: "Create a new data store", + Long: "Create a new data store", + Args: func(cmd *cobra.Command, args []string) (err error) { + if err = validate(targetType, bucketName, gcsPath, + tablePrefix, datasetName); err != nil { + return err + } + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = datastores.Create(name, targetType, projectID, bucketName, + gcsPath, datasetName, tablePrefix) + return + }, +} + +var projectID, bucketName, gcsPath, datasetName, tablePrefix string + +func init() { + CreateCmd.Flags().StringVarP(&name, "name", "n", + "", "Display name for the data store") + CreateCmd.Flags().StringVarP(&targetType, "target", "", + "", "Destination storage type. Supported types gcs or bigquery") + CreateCmd.Flags().StringVarP(&projectID, "project-id", "p", + "", "GCP project in which the datastore exists") + CreateCmd.Flags().StringVarP(&bucketName, "bucket-name", "b", + "", "Name of the Cloud Storage bucket. Required for gcs targetType") + CreateCmd.Flags().StringVarP(&gcsPath, "gcs-path", "g", + "", "Path of Cloud Storage bucket Required for gcs targetType") + CreateCmd.Flags().StringVarP(&datasetName, "dataset", "d", + "", "BigQuery dataset name Required for bigquery targetType") + CreateCmd.Flags().StringVarP(&tablePrefix, "prefix", "f", + "", "Prefix of BigQuery table Required for bigquery targetType") + + _ = CreateCmd.MarkFlagRequired("name") + _ = CreateCmd.MarkFlagRequired("target") + _ = CreateCmd.MarkFlagRequired("project-id") +} diff --git a/cmd/datastores/datastores.go b/cmd/datastores/datastores.go new file mode 100644 index 000000000..540d1f2d9 --- /dev/null +++ b/cmd/datastores/datastores.go @@ -0,0 +1,64 @@ +// 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 datastores + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +// Cmd to manage datastores +var Cmd = &cobra.Command{ + Use: "datastores", + Short: "Manage data stores to export analytics data", + Long: "Manage data stores to export analytics data", +} + +var org, name, targetType string + +func init() { + Cmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + + Cmd.AddCommand(ListCmd) + Cmd.AddCommand(GetCmd) + Cmd.AddCommand(DeleteCmd) + Cmd.AddCommand(CreateCmd) + Cmd.AddCommand(UpdateCmd) + Cmd.AddCommand(TestCmd) + + _ = Cmd.MarkFlagRequired("org") +} + +func validate(targetType string, bucketName string, gcsPath string, + tablePrefix string, datasetName string, +) (err error) { + if targetType != "gcs" && targetType != "bigquery" { + return fmt.Errorf("invalid targetType; must be gcs or bigquery") + } + if targetType == "gcs" { + if bucketName == "" || gcsPath == "" { + return fmt.Errorf("bucketName and path are mandatory parameters for gcs targetType") + } + } + if targetType == "bigquery" { + if tablePrefix == "" || datasetName == "" { + return fmt.Errorf("tablePrefix and datasetName are mandatory " + + "parameters for bigquery targetType") + } + } + return nil +} diff --git a/cmd/datastores/delete.go b/cmd/datastores/delete.go new file mode 100644 index 000000000..2e6cc14c9 --- /dev/null +++ b/cmd/datastores/delete.go @@ -0,0 +1,59 @@ +// 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 datastores + +import ( + "fmt" + + "internal/apiclient" + "internal/client/datastores" + + "github.com/spf13/cobra" +) + +// DeleteCmd to delete a datastore +var DeleteCmd = &cobra.Command{ + Use: "delete", + Short: "Deletes a datastore connection", + Long: "Deletes a datastore connection", + Args: func(cmd *cobra.Command, args []string) (err error) { + if name == "" && id == "" { + return fmt.Errorf("id or name must be passed to the command") + } + if name != "" && id != "" { + return fmt.Errorf("id and name cannot be passed together") + } + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + if id != "" { + _, err = datastores.Delete(id) + } else { + var version string + if version, err = datastores.GetVersion(name); err != nil { + return err + } + _, err = datastores.Delete(version) + } + return + }, +} + +func init() { + DeleteCmd.Flags().StringVarP(&id, "id", "i", + "", "Datastore UUID") + DeleteCmd.Flags().StringVarP(&name, "name", "n", + "", "Datastore display name") +} diff --git a/cmd/datastores/get.go b/cmd/datastores/get.go new file mode 100644 index 000000000..ae612dd74 --- /dev/null +++ b/cmd/datastores/get.go @@ -0,0 +1,59 @@ +// 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 datastores + +import ( + "fmt" + + "internal/apiclient" + "internal/client/datastores" + + "github.com/spf13/cobra" +) + +// GetCmd to get a datastore +var GetCmd = &cobra.Command{ + Use: "get", + Short: "Gets a datastore connection", + Long: "Gets a datastore connection", + Args: func(cmd *cobra.Command, args []string) (err error) { + if name == "" && id == "" { + return fmt.Errorf("id or name must be passed to the command") + } + if name != "" && id != "" { + return fmt.Errorf("id and name cannot be passed together") + } + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + if id != "" { + _, err = datastores.Get(id) + } else { + var respBody []byte + if respBody, err = datastores.GetName(name); err != nil { + return err + } + apiclient.PrettyPrint("application/json", respBody) + } + return + }, +} + +func init() { + GetCmd.Flags().StringVarP(&id, "id", "i", + "", "Datastore UUID") + GetCmd.Flags().StringVarP(&name, "name", "n", + "", "Datastore display name") +} diff --git a/cmd/datastores/list.go b/cmd/datastores/list.go new file mode 100644 index 000000000..8b33cdfc4 --- /dev/null +++ b/cmd/datastores/list.go @@ -0,0 +1,41 @@ +// 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 datastores + +import ( + "internal/apiclient" + "internal/client/datastores" + + "github.com/spf13/cobra" +) + +// ListCmd to list datastores +var ListCmd = &cobra.Command{ + Use: "list", + Short: "Returns a list of data stores in the org", + Long: "Returns a list of data stores in the org", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = datastores.List(targetType) + return + }, +} + +func init() { + ListCmd.Flags().StringVarP(&targetType, "targettype", "", + "", "TargetType is used to fetch datastores of matching type; default is fetch all") +} diff --git a/cmd/datastores/test.go b/cmd/datastores/test.go new file mode 100644 index 000000000..7ff56305b --- /dev/null +++ b/cmd/datastores/test.go @@ -0,0 +1,65 @@ +// 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 datastores + +import ( + "internal/apiclient" + "internal/client/datastores" + + "github.com/spf13/cobra" +) + +// TestCmd to update a datastore +var TestCmd = &cobra.Command{ + Use: "test", + Short: "Test an existing data store", + Long: "Test an existing data store", + Args: func(cmd *cobra.Command, args []string) (err error) { + if err = validate(targetType, bucketName, gcsPath, + tablePrefix, datasetName); err != nil { + return err + } + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = datastores.Test(id, name, targetType, projectID, bucketName, + gcsPath, datasetName, tablePrefix) + return + }, +} + +var id string + +func init() { + TestCmd.Flags().StringVarP(&name, "name", "n", + "", "Display name for the data store") + TestCmd.Flags().StringVarP(&targetType, "target", "", + "", "Destination storage type. Supported types gcs or bigquery") + TestCmd.Flags().StringVarP(&projectID, "project-id", "p", + "", "GCP project in which the datastore exists") + TestCmd.Flags().StringVarP(&bucketName, "bucket-name", "b", + "", "Name of the Cloud Storage bucket. Required for gcs targetType") + TestCmd.Flags().StringVarP(&gcsPath, "gcs-path", "g", + "", "Path of Cloud Storage bucket Required for gcs targetType") + TestCmd.Flags().StringVarP(&datasetName, "dataset", "d", + "", "BigQuery dataset name Required for bigquery targetType") + TestCmd.Flags().StringVarP(&tablePrefix, "prefix", "f", + "", "Prefix of BigQuery table Required for bigquery targetType") + + _ = TestCmd.MarkFlagRequired("id") + _ = TestCmd.MarkFlagRequired("name") + _ = TestCmd.MarkFlagRequired("target") + _ = TestCmd.MarkFlagRequired("project-id") +} diff --git a/cmd/datastores/update.go b/cmd/datastores/update.go new file mode 100644 index 000000000..76995387b --- /dev/null +++ b/cmd/datastores/update.go @@ -0,0 +1,65 @@ +// 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 datastores + +import ( + "internal/apiclient" + "internal/client/datastores" + + "github.com/spf13/cobra" +) + +// UpdateCmd to update a datastore +var UpdateCmd = &cobra.Command{ + Use: "update", + Short: "Update an existing data store", + Long: "Update an existing data store", + Args: func(cmd *cobra.Command, args []string) (err error) { + if err = validate(targetType, bucketName, gcsPath, + tablePrefix, datasetName); err != nil { + return err + } + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = datastores.Update(id, name, targetType, projectID, bucketName, + gcsPath, datasetName, tablePrefix) + return + }, +} + +func init() { + UpdateCmd.Flags().StringVarP(&id, "id", "i", + "", "Data store id") + UpdateCmd.Flags().StringVarP(&name, "name", "n", + "", "Display name for the data store") + UpdateCmd.Flags().StringVarP(&targetType, "target", "", + "", "Destination storage type. Supported types gcs or bigquery") + UpdateCmd.Flags().StringVarP(&projectID, "project-id", "p", + "", "GCP project in which the datastore exists") + UpdateCmd.Flags().StringVarP(&bucketName, "bucket-name", "b", + "", "Name of the Cloud Storage bucket. Required for gcs targetType") + UpdateCmd.Flags().StringVarP(&gcsPath, "gcs-path", "g", + "", "Path of Cloud Storage bucket Required for gcs targetType") + UpdateCmd.Flags().StringVarP(&datasetName, "dataset", "d", + "", "BigQuery dataset name Required for bigquery targetType") + UpdateCmd.Flags().StringVarP(&tablePrefix, "prefix", "f", + "", "Prefix of BigQuery table Required for bigquery targetType") + + _ = UpdateCmd.MarkFlagRequired("id") + _ = UpdateCmd.MarkFlagRequired("name") + _ = UpdateCmd.MarkFlagRequired("target") + _ = UpdateCmd.MarkFlagRequired("project-id") +} diff --git a/cmd/env/crtsecactions.go b/cmd/env/crtsecactions.go new file mode 100644 index 000000000..19e9dac92 --- /dev/null +++ b/cmd/env/crtsecactions.go @@ -0,0 +1,53 @@ +// 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 env + +import ( + "internal/apiclient" + "internal/client/env" + + "github.com/apigee/apigeecli/cmd/utils" + "github.com/spf13/cobra" +) + +// CreateSecActCmd to get a securityaction +var CreateSecActCmd = &cobra.Command{ + Use: "create", + Short: "Create a new SecurityAction", + Long: "Create a new SecurityAction", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + content, err := utils.ReadFile(securityActionFile) + if err != nil { + return err + } + _, err = env.CreateSecurityAction(name, content) + return + }, +} + +var securityActionFile string + +func init() { + CreateSecActCmd.Flags().StringVarP(&name, "name", "n", + "", "Security Action name") + CreateSecActCmd.Flags().StringVarP(&securityActionFile, "file", "f", + "", "Path to a file containing Security Action content") + _ = CreateSecActCmd.MarkFlagRequired("name") + _ = CreateSecActCmd.MarkFlagRequired("file") +} diff --git a/cmd/env/disablesecactions.go b/cmd/env/disablesecactions.go new file mode 100644 index 000000000..ce1bafdcb --- /dev/null +++ b/cmd/env/disablesecactions.go @@ -0,0 +1,44 @@ +// Copyright 2020 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 env + +import ( + "internal/apiclient" + + environments "internal/client/env" + + "github.com/spf13/cobra" +) + +// DisableSecActCmd to manage tracing of apis +var DisableSecActCmd = &cobra.Command{ + Use: "disable", + Short: "Disable a SecurityAction", + Long: "Disable a SecurityAction", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = environments.DisableSecurityAction(name) + return + }, +} + +func init() { + DisableSecActCmd.Flags().StringVarP(&name, "name", "n", + "", "Security Action name") + _ = DisableSecActCmd.MarkFlagRequired("name") +} diff --git a/cmd/env/disablesectionscfg.go b/cmd/env/disablesectionscfg.go new file mode 100644 index 000000000..848ed85a1 --- /dev/null +++ b/cmd/env/disablesectionscfg.go @@ -0,0 +1,38 @@ +// Copyright 2020 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 env + +import ( + "internal/apiclient" + + environments "internal/client/env" + + "github.com/spf13/cobra" +) + +// DisableSecActCfgCmd to manage tracing of apis +var DisableSecActCfgCmd = &cobra.Command{ + Use: "disable", + Short: "Disables SecurityActions on the environment", + Long: "Disables SecurityActions on the environment", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = environments.UpdateSecurityActionsConfig(false) + return + }, +} diff --git a/cmd/env/enablesecactions.go b/cmd/env/enablesecactions.go new file mode 100644 index 000000000..126fb0b47 --- /dev/null +++ b/cmd/env/enablesecactions.go @@ -0,0 +1,44 @@ +// Copyright 2020 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 env + +import ( + "internal/apiclient" + + environments "internal/client/env" + + "github.com/spf13/cobra" +) + +// EnableSecActCmd to manage tracing of apis +var EnableSecActCmd = &cobra.Command{ + Use: "enable", + Short: "Enable a SecurityAction", + Long: "Enable a SecurityAction", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = environments.EnableSecurityAction(name) + return + }, +} + +func init() { + EnableSecActCmd.Flags().StringVarP(&name, "name", "n", + "", "Security Action name") + _ = EnableSecActCmd.MarkFlagRequired("name") +} diff --git a/cmd/env/enablesectionscfg.go b/cmd/env/enablesectionscfg.go new file mode 100644 index 000000000..ddea7de86 --- /dev/null +++ b/cmd/env/enablesectionscfg.go @@ -0,0 +1,38 @@ +// Copyright 2020 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 env + +import ( + "internal/apiclient" + + environments "internal/client/env" + + "github.com/spf13/cobra" +) + +// EnableSecActCfgCmd to manage tracing of apis +var EnableSecActCfgCmd = &cobra.Command{ + Use: "enable", + Short: "Enables SecurityActions on the environment", + Long: "Enables SecurityActions on the environment", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = environments.UpdateSecurityActionsConfig(true) + return + }, +} diff --git a/cmd/env/env.go b/cmd/env/env.go index 2c3583774..99717c62c 100644 --- a/cmd/env/env.go +++ b/cmd/env/env.go @@ -43,4 +43,7 @@ func init() { Cmd.AddCommand(DeployCmd) Cmd.AddCommand(TraceConfigCmd) Cmd.AddCommand(ArchiveCmd) + Cmd.AddCommand(SecInCmd) + Cmd.AddCommand(SecActCmd) + Cmd.AddCommand(SecActCfgCmd) } diff --git a/cmd/env/getsecactions.go b/cmd/env/getsecactions.go new file mode 100644 index 000000000..fd4a20ee3 --- /dev/null +++ b/cmd/env/getsecactions.go @@ -0,0 +1,43 @@ +// 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 env + +import ( + "internal/apiclient" + "internal/client/env" + + "github.com/spf13/cobra" +) + +// GetSecActCmd to get a securityaction +var GetSecActCmd = &cobra.Command{ + Use: "get", + Short: "Get a SecurityAction by name", + Long: "Get a SecurityAction by name", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = env.GetSecurityAction(name) + return + }, +} + +func init() { + GetSecActCmd.Flags().StringVarP(&name, "name", "n", + "", "Security Action name") + _ = GetSecActCmd.MarkFlagRequired("name") +} diff --git a/cmd/env/getsecactionscfg.go b/cmd/env/getsecactionscfg.go new file mode 100644 index 000000000..d1b25fb67 --- /dev/null +++ b/cmd/env/getsecactionscfg.go @@ -0,0 +1,38 @@ +// Copyright 2020 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 env + +import ( + "internal/apiclient" + + environments "internal/client/env" + + "github.com/spf13/cobra" +) + +// GetSecActCfgCmd to manage tracing of apis +var GetSecActCfgCmd = &cobra.Command{ + Use: "get", + Short: "Returns the current SecurityActions configuration", + Long: "Returns the current SecurityActions configuration", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = environments.GetSecurityActionsConfig() + return + }, +} diff --git a/cmd/env/getsecin.go b/cmd/env/getsecin.go new file mode 100644 index 000000000..565cc53ff --- /dev/null +++ b/cmd/env/getsecin.go @@ -0,0 +1,43 @@ +// 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 env + +import ( + "internal/apiclient" + "internal/client/env" + + "github.com/spf13/cobra" +) + +// GetSecInCmd returns security incidents +var GetSecInCmd = &cobra.Command{ + Use: "get", + Short: "Returns a security incidents by name", + Long: "Returns a security incidents by name", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = env.GetSecurityIncident(name) + return + }, +} + +func init() { + GetSecInCmd.Flags().StringVarP(&name, "name", "n", + "", "Name of the security incident") + _ = GetSecInCmd.MarkFlagRequired("name") +} diff --git a/cmd/env/getsecreport.go b/cmd/env/getsecreport.go new file mode 100644 index 000000000..11daeeda7 --- /dev/null +++ b/cmd/env/getsecreport.go @@ -0,0 +1,43 @@ +// 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 env + +import ( + "internal/apiclient" + "internal/client/env" + + "github.com/spf13/cobra" +) + +// GetSecReportCmd returns security incidents +var GetSecReportCmd = &cobra.Command{ + Use: "get", + Short: "Returns a security reports by name", + Long: "Returns a security reports by name", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = env.GetSecurityReport(name) + return + }, +} + +func init() { + GetSecReportCmd.Flags().StringVarP(&name, "name", "n", + "", "Name of the security report") + _ = GetSecReportCmd.MarkFlagRequired("name") +} diff --git a/cmd/env/listsecact.go b/cmd/env/listsecact.go new file mode 100644 index 000000000..83832aa67 --- /dev/null +++ b/cmd/env/listsecact.go @@ -0,0 +1,46 @@ +// 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 env + +import ( + "internal/apiclient" + "internal/client/env" + + "github.com/spf13/cobra" +) + +// ListSecActCmd to list catalog items +var ListSecActCmd = &cobra.Command{ + Use: "list", + Short: "Returns security actions in the environment", + Long: "Returns security actions in the environment", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = env.ListSecurityActions(pageSize, pageToken, filter) + return + }, +} + +func init() { + ListSecActCmd.Flags().IntVarP(&pageSize, "pageSize", "", + -1, "The maximum number of versions to return") + ListSecActCmd.Flags().StringVarP(&pageToken, "pageToken", "", + "", "A page token, received from a previous call") + ListSecActCmd.Flags().StringVarP(&filter, "filter", "", + "", "Filter results") +} diff --git a/cmd/env/listsecin.go b/cmd/env/listsecin.go new file mode 100644 index 000000000..086aa7d4e --- /dev/null +++ b/cmd/env/listsecin.go @@ -0,0 +1,51 @@ +// 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 env + +import ( + "internal/apiclient" + "internal/client/env" + + "github.com/spf13/cobra" +) + +// ListSecInCmd to list catalog items +var ListSecInCmd = &cobra.Command{ + Use: "list", + Short: "Returns security incidents in the environment", + Long: "Returns security incidents in the environment", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = env.ListSecurityIncidents(pageSize, pageToken, filter) + return + }, +} + +var ( + pageToken, filter string + pageSize int +) + +func init() { + ListSecInCmd.Flags().IntVarP(&pageSize, "pageSize", "", + -1, "The maximum number of versions to return") + ListSecInCmd.Flags().StringVarP(&pageToken, "pageToken", "", + "", "A page token, received from a previous call") + ListSecInCmd.Flags().StringVarP(&filter, "filter", "", + "", "Filter results") +} diff --git a/cmd/env/listsecreports.go b/cmd/env/listsecreports.go new file mode 100644 index 000000000..ec42846f5 --- /dev/null +++ b/cmd/env/listsecreports.go @@ -0,0 +1,57 @@ +// 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 env + +import ( + "internal/apiclient" + "internal/client/env" + + "github.com/spf13/cobra" +) + +// ListSecReportCmd returns security incidents +var ListSecReportCmd = &cobra.Command{ + Use: "get", + Short: "Returns a security reports by name", + Long: "Returns a security reports by name", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = env.ListSecurityReports(pageSize, pageToken, dataset, to, + from, status, submittedBy) + return + }, +} + +var from, to, dataset, status, submittedBy string + +func init() { + ListSecReportCmd.Flags().IntVarP(&pageSize, "pageSize", "", + -1, "The maximum number of versions to return") + ListSecReportCmd.Flags().StringVarP(&pageToken, "pageToken", "", + "", "A page token, received from a previous call") + ListSecReportCmd.Flags().StringVarP(&from, "from", "f", + "", "Filter response list by returning security reports that created after this date time") + ListSecReportCmd.Flags().StringVarP(&to, "to", "", + "", "Filter response list by returning security reports that created before this date time") + ListSecReportCmd.Flags().StringVarP(&dataset, "dataset", "d", + "", "Filter response list by dataset; example api, mint") + ListSecReportCmd.Flags().StringVarP(&status, "status", "s", + "", "Filter response list by security reports status") + ListSecReportCmd.Flags().StringVarP(&submittedBy, "submitted-by", "u", + "", "Filter response list by user who submitted queries") +} diff --git a/cmd/env/secactioncfg.go b/cmd/env/secactioncfg.go new file mode 100644 index 000000000..4fc365f93 --- /dev/null +++ b/cmd/env/secactioncfg.go @@ -0,0 +1,37 @@ +// 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 env + +import ( + "github.com/spf13/cobra" +) + +// SecActCfgCmd to manage security incidents +var SecActCfgCmd = &cobra.Command{ + Use: "secactionscfg", + Short: "Manage SecurityActionsConfig for Apigee Advanced Security", + Long: "Manage SecurityActionsConfig for Apigee Advanced Security", +} + +func init() { + SecActCfgCmd.PersistentFlags().StringVarP(&environment, "env", "e", + "", "Apigee environment name") + + SecActCfgCmd.AddCommand(GetSecActCfgCmd) + SecActCfgCmd.AddCommand(EnableSecActCfgCmd) + SecActCfgCmd.AddCommand(DisableSecActCfgCmd) + + _ = SecActCfgCmd.MarkPersistentFlagRequired("env") +} diff --git a/cmd/env/secactions.go b/cmd/env/secactions.go new file mode 100644 index 000000000..18c4309f1 --- /dev/null +++ b/cmd/env/secactions.go @@ -0,0 +1,39 @@ +// 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 env + +import ( + "github.com/spf13/cobra" +) + +// SecActCmd to manage security incidents +var SecActCmd = &cobra.Command{ + Use: "secactions", + Short: "Manage SecurityActions for Apigee Advanced Security", + Long: "Manage SecurityActions for Apigee Advanced Security", +} + +func init() { + SecActCmd.PersistentFlags().StringVarP(&environment, "env", "e", + "", "Apigee environment name") + + _ = SecActCmd.MarkPersistentFlagRequired("env") + + SecActCmd.AddCommand(ListSecActCmd) + SecActCmd.AddCommand(GetSecActCmd) + SecActCmd.AddCommand(EnableSecActCmd) + SecActCmd.AddCommand(DisableSecActCmd) + SecActCmd.AddCommand(CreateSecActCmd) +} diff --git a/cmd/env/secincidents.go b/cmd/env/secincidents.go new file mode 100644 index 000000000..ee70ecd5e --- /dev/null +++ b/cmd/env/secincidents.go @@ -0,0 +1,36 @@ +// 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 env + +import ( + "github.com/spf13/cobra" +) + +// SecInCmd to manage security incidents +var SecInCmd = &cobra.Command{ + Use: "secincidents", + Short: "View SecurityIncidents from Apigee Advanced Security", + Long: "View SecurityIncidents from Apigee Advanced Security", +} + +func init() { + SecInCmd.PersistentFlags().StringVarP(&environment, "env", "e", + "", "Apigee environment name") + + _ = SecInCmd.MarkPersistentFlagRequired("env") + + SecInCmd.AddCommand(ListSecInCmd) + SecInCmd.AddCommand(GetSecInCmd) +} diff --git a/cmd/env/secreports.go b/cmd/env/secreports.go new file mode 100644 index 000000000..959004c53 --- /dev/null +++ b/cmd/env/secreports.go @@ -0,0 +1,36 @@ +// 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 env + +import ( + "github.com/spf13/cobra" +) + +// SecReportCmd to manage security reports +var SecReportCmd = &cobra.Command{ + Use: "secreports", + Short: "Manage SecurityReports for Apigee Advanced Security", + Long: "View SecurityReports for Apigee Advanced Security", +} + +func init() { + SecReportCmd.PersistentFlags().StringVarP(&environment, "env", "e", + "", "Apigee environment name") + + _ = SecReportCmd.MarkPersistentFlagRequired("env") + + SecReportCmd.AddCommand(ListSecReportCmd) + SecReportCmd.AddCommand(GetSecReportCmd) +} diff --git a/cmd/org/createorg.go b/cmd/org/createorg.go index 7aedb86f3..10feb9b8b 100644 --- a/cmd/org/createorg.go +++ b/cmd/org/createorg.go @@ -44,47 +44,54 @@ var CreateCmd = &cobra.Command{ if billingType != SUBSCRIPTION && billingType != EVALUATION { return fmt.Errorf("billing type must be %s or %s", SUBSCRIPTION, EVALUATION) } - - if runtimeType == CLOUD { - if network == "" { - return fmt.Errorf("authorized network must be supplied") - } - if databaseKey == "" { - return fmt.Errorf("runtime database encryption key must be supplied") - } - } apiclient.SetProjectID(projectID) return apiclient.SetApigeeOrg(projectID) }, RunE: func(cmd *cobra.Command, args []string) (err error) { - _, err = orgs.Create(region, network, runtimeType, databaseKey, billingType, disablePortal) + _, err = orgs.Create(description, analyticsRegion, authorizedNetwork, + disableVpcPeering, runtimeType, billingType, runtimeDatabaseEncryptionKeyName, + portalDisabled, apiConsumerDataEncryptionKeyName, controlPlaneEncryptionKeyName, + apiConsumerDataLocation) return }, } var ( - region, projectID, network, runtimeType, description, databaseKey, billingType string - disablePortal bool + analyticsRegion, projectID, authorizedNetwork, runtimeType string + description, runtimeDatabaseEncryptionKeyName, billingType string + apiConsumerDataEncryptionKeyName, controlPlaneEncryptionKeyName, apiConsumerDataLocation string + disableVpcPeering, portalDisabled bool ) func init() { - CreateCmd.Flags().StringVarP(®ion, "reg", "r", - "", "Analytics region name") - CreateCmd.Flags().StringVarP(&projectID, "prj", "p", - "", "GCP Project ID") CreateCmd.Flags().StringVarP(&description, "desc", "d", "", "Apigee org description") - CreateCmd.Flags().StringVarP(&network, "net", "n", - "default", "Authorized network; if using a shared VPC format is "+ - "projects/{host-project-id}/{location}/networks/{network-name}") - CreateCmd.Flags().StringVarP(&databaseKey, "key", "k", - "", "Runtime Database Encryption Key") + CreateCmd.Flags().StringVarP(&analyticsRegion, "reg", "r", + "", "Analytics region name") + CreateCmd.Flags().BoolVarP(&disableVpcPeering, "disable-vpc-peering", "", + true, "Disable VPC Peering; default true") CreateCmd.Flags().StringVarP(&runtimeType, "runtime-type", "", HYBRID, "Runtime type: CLOUD or HYBRID") CreateCmd.Flags().StringVarP(&runtimeType, "billing-type", "", "", "Billing type: SUBSCRIPTION or EVALUATION") - CreateCmd.Flags().BoolVarP(&disablePortal, "disable-portal", "", - false, "Disable creation of Developer Portals") + CreateCmd.Flags().StringVarP(&runtimeDatabaseEncryptionKeyName, "runtime-key", "", + "", "Runtime Database Encryption Key") + CreateCmd.Flags().StringVarP(&apiConsumerDataEncryptionKeyName, "consumer-key", "", + "", "API Consumer Data Encryption Key") + CreateCmd.Flags().StringVarP(&controlPlaneEncryptionKeyName, "controlplane-key", "", + "", "Apigee Controlplane Encryption Key") + CreateCmd.Flags().StringVarP(&apiConsumerDataLocation, "key", "k", + "", "API Consumer data location") + + CreateCmd.Flags().StringVarP(&projectID, "prj", "p", + "", "GCP Project ID") + + CreateCmd.Flags().StringVarP(&authorizedNetwork, "net", "n", + "default", "Authorized network; if using a shared VPC format is "+ + "projects/{host-project-id}/{location}/networks/{network-name}") + + CreateCmd.Flags().BoolVarP(&portalDisabled, "disable-portal", "", + false, "Disable creation of Developer Portals; default false") _ = CreateCmd.MarkFlagRequired("prj") _ = CreateCmd.MarkFlagRequired("reg") diff --git a/cmd/org/export.go b/cmd/org/export.go index 931ce2775..450735eb0 100644 --- a/cmd/org/export.go +++ b/cmd/org/export.go @@ -38,6 +38,7 @@ import ( "internal/client/orgs" "internal/client/products" "internal/client/references" + "internal/client/securityprofiles" "internal/client/sharedflows" "internal/client/sync" "internal/client/targetservers" @@ -172,6 +173,13 @@ var ExportCmd = &cobra.Command{ return err } + if orgs.GetAddOn("apiSecurityConfig") { + clilog.Info.Println("Exporting API Security Configuration...") + if err = securityprofiles.Export(conn, folder, allRevisions); proceedOnError(err) != nil { + return err + } + } + if runtimeType == "HYBRID" { clilog.Info.Println("Exporting Sync Authorization Identities...") if respBody, err = sync.Get(); err != nil { @@ -289,7 +297,8 @@ func init() { ExportCmd.Flags().BoolVarP(&cleanPath, "clean", "", false, "clean folder or files and directories before export") ExportCmd.Flags().BoolVarP(&allRevisions, "all", "", - false, "Export all revisions, default=false. Exports the latest revision") + false, "Export all revisions, default=false. Exports the latest revision."+ + "Applies to proxies, sf and sec profiles") ExportCmd.Flags().BoolVarP(&continueOnErr, "continueOnError", "", false, "Ignore errors and continue exporting data") } diff --git a/cmd/org/updateorg.go b/cmd/org/updateorg.go index 6dae751c1..a53415350 100644 --- a/cmd/org/updateorg.go +++ b/cmd/org/updateorg.go @@ -33,35 +33,21 @@ var UpdateCmd = &cobra.Command{ if runtimeType != "HYBRID" && runtimeType != "CLOUD" { return fmt.Errorf("runtime type must be CLOUD or HYBRID") } - if runtimeType == "CLOUD" { - if network == "" { - return fmt.Errorf("authorized network must be supplied") - } - if databaseKey == "" { - return fmt.Errorf("runtime database encryption key must be supplied") - } - } apiclient.SetProjectID(projectID) return apiclient.SetApigeeOrg(projectID) }, RunE: func(cmd *cobra.Command, args []string) (err error) { - _, err = orgs.Update(description, "", region, network, runtimeType, databaseKey) + _, err = orgs.Update(description, authorizedNetwork) return }, } func init() { - UpdateCmd.Flags().StringVarP(®ion, "reg", "r", - "", "Analytics region name") UpdateCmd.Flags().StringVarP(&description, "desc", "d", "", "Apigee org description") - UpdateCmd.Flags().StringVarP(&network, "net", "n", + UpdateCmd.Flags().StringVarP(&authorizedNetwork, "net", "n", "default", "Authorized network; if using a shared VPC format is "+ "projects/{host-project-id}/{location}/networks/{network-name}") - UpdateCmd.Flags().StringVarP(&databaseKey, "key", "k", - "", "Runtime Database Encryption Key") - UpdateCmd.Flags().StringVarP(&runtimeType, "runtime-type", "", - "HYBRID", "Runtime type: CLOUD or HYBRID") _ = UpdateCmd.MarkFlagRequired("prj") _ = UpdateCmd.MarkFlagRequired("reg") diff --git a/cmd/root.go b/cmd/root.go index 2cbe48c79..d1f126c17 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -27,11 +27,14 @@ import ( "internal/clilog" + "github.com/apigee/apigeecli/cmd/apicategories" + "github.com/apigee/apigeecli/cmd/apidocs" "github.com/apigee/apigeecli/cmd/apis" "github.com/apigee/apigeecli/cmd/appgroups" "github.com/apigee/apigeecli/cmd/apps" cache "github.com/apigee/apigeecli/cmd/cache" "github.com/apigee/apigeecli/cmd/datacollectors" + "github.com/apigee/apigeecli/cmd/datastores" "github.com/apigee/apigeecli/cmd/developers" "github.com/apigee/apigeecli/cmd/env" "github.com/apigee/apigeecli/cmd/envgroup" @@ -49,6 +52,7 @@ import ( "github.com/apigee/apigeecli/cmd/projects" "github.com/apigee/apigeecli/cmd/references" res "github.com/apigee/apigeecli/cmd/res" + "github.com/apigee/apigeecli/cmd/securityprofiles" "github.com/apigee/apigeecli/cmd/sharedflows" "github.com/apigee/apigeecli/cmd/sync" targetservers "github.com/apigee/apigeecli/cmd/targetservers" @@ -172,6 +176,10 @@ func init() { RootCmd.AddCommand(preferences.Cmd) RootCmd.AddCommand(eptattachment.Cmd) RootCmd.AddCommand(appgroups.Cmd) + RootCmd.AddCommand(apidocs.Cmd) + RootCmd.AddCommand(apicategories.Cmd) + RootCmd.AddCommand(datastores.Cmd) + RootCmd.AddCommand(securityprofiles.Cmd) } func initConfig() { diff --git a/cmd/securityprofiles/attach.go b/cmd/securityprofiles/attach.go new file mode 100644 index 000000000..225fb8018 --- /dev/null +++ b/cmd/securityprofiles/attach.go @@ -0,0 +1,51 @@ +// 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 securityprofiles + +import ( + "internal/apiclient" + "internal/client/securityprofiles" + + "github.com/spf13/cobra" +) + +// AttachCmd to list catalog items +var AttachCmd = &cobra.Command{ + Use: "attach", + Short: "Attach a security profile to an environment", + Long: "Attach a security profile to an environment", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = securityprofiles.Attach(name, revision) + return + }, +} + +var environment, revision string + +func init() { + AttachCmd.Flags().StringVarP(&name, "name", "n", + "", "Name of the security profile") + AttachCmd.Flags().StringVarP(&environment, "env", "e", + "", "Apigee environment name") + AttachCmd.Flags().StringVarP(&revision, "rev", "r", + "", "Security Profile revision id") + _ = AttachCmd.MarkFlagRequired("name") + _ = AttachCmd.MarkFlagRequired("env") + _ = AttachCmd.MarkFlagRequired("rev") +} diff --git a/cmd/securityprofiles/create.go b/cmd/securityprofiles/create.go new file mode 100644 index 000000000..c9c80320c --- /dev/null +++ b/cmd/securityprofiles/create.go @@ -0,0 +1,52 @@ +// 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 securityprofiles + +import ( + "internal/apiclient" + "internal/client/securityprofiles" + + "github.com/apigee/apigeecli/cmd/utils" + "github.com/spf13/cobra" +) + +// CreateCmd to get a securityprofile +var CreateCmd = &cobra.Command{ + Use: "create", + Short: "Create a new Security Profile", + Long: "Create a new Security Profile", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + content, err := utils.ReadFile(securityActionFile) + if err != nil { + return err + } + _, err = securityprofiles.Create(name, content) + return + }, +} + +var securityActionFile string + +func init() { + CreateCmd.Flags().StringVarP(&name, "name", "n", + "", "Name of the security profile") + CreateCmd.Flags().StringVarP(&securityActionFile, "file", "f", + "", "Path to a file containing Security Profile content") + _ = CreateCmd.MarkFlagRequired("name") + _ = CreateCmd.MarkFlagRequired("file") +} diff --git a/cmd/securityprofiles/delete.go b/cmd/securityprofiles/delete.go new file mode 100644 index 000000000..37d7b1ca4 --- /dev/null +++ b/cmd/securityprofiles/delete.go @@ -0,0 +1,42 @@ +// 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 securityprofiles + +import ( + "internal/apiclient" + "internal/client/securityprofiles" + + "github.com/spf13/cobra" +) + +// DeleteCmd to list catalog items +var DeleteCmd = &cobra.Command{ + Use: "delete", + Short: "Deletes a security profile", + Long: "Deletes a security profile", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = securityprofiles.Delete(name) + return + }, +} + +func init() { + DeleteCmd.Flags().StringVarP(&name, "name", "n", + "", "Name of the security profile") + _ = DeleteCmd.MarkFlagRequired("name") +} diff --git a/cmd/securityprofiles/detach.go b/cmd/securityprofiles/detach.go new file mode 100644 index 000000000..ace61c770 --- /dev/null +++ b/cmd/securityprofiles/detach.go @@ -0,0 +1,46 @@ +// 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 securityprofiles + +import ( + "internal/apiclient" + "internal/client/securityprofiles" + + "github.com/spf13/cobra" +) + +// DetachCmd to list catalog items +var DetachCmd = &cobra.Command{ + Use: "detach", + Short: "Detach a security profile from an environment", + Long: "Detach a security profile from an environment", + Args: func(cmd *cobra.Command, args []string) (err error) { + apiclient.SetApigeeEnv(environment) + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = securityprofiles.Detach(name) + return + }, +} + +func init() { + DetachCmd.Flags().StringVarP(&name, "name", "n", + "", "Name of the security profile") + DetachCmd.Flags().StringVarP(&environment, "env", "e", + "", "Apigee environment name") + _ = DetachCmd.MarkFlagRequired("name") + _ = DetachCmd.MarkFlagRequired("env") +} diff --git a/cmd/securityprofiles/export.go b/cmd/securityprofiles/export.go new file mode 100644 index 000000000..6ce904add --- /dev/null +++ b/cmd/securityprofiles/export.go @@ -0,0 +1,59 @@ +// Copyright 2020 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 securityprofiles + +import ( + "os" + + "internal/apiclient" + + "internal/client/securityprofiles" + + "github.com/spf13/cobra" +) + +// ExpCmd to export sec profiles +var ExpCmd = &cobra.Command{ + Use: "export", + Short: "Export Security Profiles to a file", + Long: "Export Security Profiles to a file", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + if folder == "" { + folder, _ = os.Getwd() + } + if err = apiclient.FolderExists(folder); err != nil { + return err + } + return securityprofiles.Export(conn, folder, allRevisions) + }, +} + +var ( + conn int + folder string + allRevisions bool +) + +func init() { + ExpCmd.Flags().IntVarP(&conn, "conn", "c", + 4, "Number of connections") + ExpCmd.Flags().StringVarP(&folder, "folder", "f", + "", "folder to export Security Profiles") + ExpCmd.Flags().BoolVarP(&allRevisions, "all", "", + false, "Export all proxy revisions") +} diff --git a/cmd/securityprofiles/get.go b/cmd/securityprofiles/get.go new file mode 100644 index 000000000..93a23a78b --- /dev/null +++ b/cmd/securityprofiles/get.go @@ -0,0 +1,46 @@ +// 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 securityprofiles + +import ( + "internal/apiclient" + "internal/client/securityprofiles" + + "github.com/spf13/cobra" +) + +// GetCmd to list catalog items +var GetCmd = &cobra.Command{ + Use: "get", + Short: "Returns a security profile by name", + Long: "Returns a security profile by name", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = securityprofiles.Get(name, revision) + return + }, +} + +var name string + +func init() { + GetCmd.Flags().StringVarP(&name, "name", "n", + "", "Name of the security profile") + GetCmd.Flags().StringVarP(&revision, "revision", "r", + "", "Revision of the security profile") + _ = GetCmd.MarkFlagRequired("name") +} diff --git a/cmd/securityprofiles/list.go b/cmd/securityprofiles/list.go new file mode 100644 index 000000000..029d1347b --- /dev/null +++ b/cmd/securityprofiles/list.go @@ -0,0 +1,48 @@ +// 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 securityprofiles + +import ( + "internal/apiclient" + "internal/client/securityprofiles" + + "github.com/spf13/cobra" +) + +// ListCmd to list catalog items +var ListCmd = &cobra.Command{ + Use: "list", + Short: "Returns the security profiles in the org", + Long: "Returns the security profiles in the org", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = securityprofiles.List(pageSize, pageToken) + return + }, +} + +var ( + pageSize int + pageToken string +) + +func init() { + ListCmd.Flags().IntVarP(&pageSize, "pageSize", "", + -1, "The maximum number of versions to return") + ListCmd.Flags().StringVarP(&pageToken, "pageToken", "", + "", "A page token, received from a previous call") +} diff --git a/cmd/securityprofiles/listrevisions.go b/cmd/securityprofiles/listrevisions.go new file mode 100644 index 000000000..bf00283c4 --- /dev/null +++ b/cmd/securityprofiles/listrevisions.go @@ -0,0 +1,42 @@ +// 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 securityprofiles + +import ( + "internal/apiclient" + "internal/client/securityprofiles" + + "github.com/spf13/cobra" +) + +// ListRevisionsCmd to list catalog items +var ListRevisionsCmd = &cobra.Command{ + Use: "listrevisions", + Short: "Returns the revisions of a security profile", + Long: "Returns the revisions of a security profile", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + _, err = securityprofiles.ListRevisions(name) + return + }, +} + +func init() { + ListRevisionsCmd.Flags().StringVarP(&name, "name", "n", + "", "Name of the security profile") + _ = ListRevisionsCmd.MarkFlagRequired("name") +} diff --git a/cmd/securityprofiles/securityprofiles.go b/cmd/securityprofiles/securityprofiles.go new file mode 100644 index 000000000..99477f05e --- /dev/null +++ b/cmd/securityprofiles/securityprofiles.go @@ -0,0 +1,46 @@ +// 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 securityprofiles + +import ( + "github.com/spf13/cobra" +) + +// Cmd to manage apis +var Cmd = &cobra.Command{ + Use: "securityprofiles", + Aliases: []string{"secprofiles"}, + Short: "Manage Adv API Security Profiles", + Long: "Manage Adv API Security Profiles", +} + +var org string + +func init() { + Cmd.PersistentFlags().StringVarP(&org, "org", "o", + "", "Apigee organization name") + + Cmd.AddCommand(ListCmd) + Cmd.AddCommand(GetCmd) + Cmd.AddCommand(DeleteCmd) + Cmd.AddCommand(AttachCmd) + Cmd.AddCommand(DetachCmd) + Cmd.AddCommand(CreateCmd) + Cmd.AddCommand(ListRevisionsCmd) + Cmd.AddCommand(UpdateCmd) + Cmd.AddCommand(ExpCmd) + + _ = Cmd.MarkFlagRequired("org") +} diff --git a/cmd/securityprofiles/update.go b/cmd/securityprofiles/update.go new file mode 100644 index 000000000..ac1a3cd0a --- /dev/null +++ b/cmd/securityprofiles/update.go @@ -0,0 +1,50 @@ +// 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 securityprofiles + +import ( + "internal/apiclient" + "internal/client/securityprofiles" + + "github.com/apigee/apigeecli/cmd/utils" + "github.com/spf13/cobra" +) + +// UpdateCmd to update a security profile +var UpdateCmd = &cobra.Command{ + Use: "update", + Short: "Update an existing Security Profile", + Long: "Update an existing Security Profile", + Args: func(cmd *cobra.Command, args []string) (err error) { + return apiclient.SetApigeeOrg(org) + }, + RunE: func(cmd *cobra.Command, args []string) (err error) { + content, err := utils.ReadFile(securityActionFile) + if err != nil { + return err + } + _, err = securityprofiles.Update(name, content) + return + }, +} + +func init() { + UpdateCmd.Flags().StringVarP(&name, "name", "n", + "", "Name of the security profile") + UpdateCmd.Flags().StringVarP(&securityActionFile, "file", "f", + "", "Path to a file containing Security Profile content") + _ = UpdateCmd.MarkFlagRequired("name") + _ = UpdateCmd.MarkFlagRequired("file") +} diff --git a/internal/apiclient/httpclient.go b/internal/apiclient/httpclient.go index 05b48676c..d9cea7771 100644 --- a/internal/apiclient/httpclient.go +++ b/internal/apiclient/httpclient.go @@ -283,10 +283,10 @@ func HttpClient(params ...string) (respBody []byte, err error) { switch paramLen := len(params); paramLen { case 1: - req, err = http.NewRequest("GET", params[0], nil) + req, err = http.NewRequest(http.MethodGet, params[0], nil) case 2: clilog.Debug.Println("Payload: ", params[1]) - req, err = http.NewRequest("POST", params[0], bytes.NewBuffer([]byte(params[1]))) + req, err = http.NewRequest(http.MethodPost, params[0], bytes.NewBuffer([]byte(params[1]))) case 3: if req, err = getRequest(params); err != nil { return nil, err @@ -405,16 +405,16 @@ func GetHttpClient() (err error) { func getRequest(params []string) (req *http.Request, err error) { if params[2] == "DELETE" { - req, err = http.NewRequest("DELETE", params[0], nil) + req, err = http.NewRequest(http.MethodDelete, params[0], nil) } else if params[2] == "PUT" { clilog.Debug.Println("Payload: ", params[1]) - req, err = http.NewRequest("PUT", params[0], bytes.NewBuffer([]byte(params[1]))) + req, err = http.NewRequest(http.MethodPut, params[0], bytes.NewBuffer([]byte(params[1]))) } else if params[2] == "PATCH" { clilog.Debug.Println("Payload: ", params[1]) - req, err = http.NewRequest("PATCH", params[0], bytes.NewBuffer([]byte(params[1]))) + req, err = http.NewRequest(http.MethodPatch, params[0], bytes.NewBuffer([]byte(params[1]))) } else if params[2] == "POST" { clilog.Debug.Println("Payload: ", params[1]) - req, err = http.NewRequest("POST", params[0], bytes.NewBuffer([]byte(params[1]))) + req, err = http.NewRequest(http.MethodPost, params[0], bytes.NewBuffer([]byte(params[1]))) } else { return nil, errors.New("unsupported method") } diff --git a/internal/client/apicategories/apicategories.go b/internal/client/apicategories/apicategories.go new file mode 100644 index 000000000..22d14a411 --- /dev/null +++ b/internal/client/apicategories/apicategories.go @@ -0,0 +1,71 @@ +// 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 apicategories + +import ( + "net/url" + "path" + "strings" + + "internal/apiclient" +) + +// Create +func Create(siteid string, name string) (respBody []byte, err error) { + apicategories := []string{} + apicategories = append(apicategories, "\"siteId\":"+"\""+siteid+"\"") + apicategories = append(apicategories, "\"name\":"+"\""+name+"\"") + payload := "{" + strings.Join(apicategories, ",") + "}" + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "sites", siteid, "apicategories") + respBody, err = apiclient.HttpClient(u.String(), payload) + return respBody, err +} + +// Get +func Get(siteid string, name string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "sites", siteid, "apicategories", name) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// List +func List(siteid string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "sites", siteid, "apicategories") + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// Delete +func Delete(siteid string, name string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "sites", siteid, "apicategories", name) + respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") + return respBody, err +} + +// Update +func Update(siteid string, name string) (respBody []byte, err error) { + apicategories := []string{} + apicategories = append(apicategories, "\"siteId\":"+"\""+siteid+"\"") + apicategories = append(apicategories, "\"name\":"+"\""+name+"\"") + payload := "{" + strings.Join(apicategories, ",") + "}" + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "sites", siteid, "apicategories") + respBody, err = apiclient.HttpClient(u.String(), payload, "PATCH") + return respBody, err +} diff --git a/internal/client/apidocs/apidocs.go b/internal/client/apidocs/apidocs.go new file mode 100644 index 000000000..affc67ff3 --- /dev/null +++ b/internal/client/apidocs/apidocs.go @@ -0,0 +1,157 @@ +// 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 apidocs + +import ( + "net/url" + "path" + "strings" + + "internal/apiclient" +) + +type Action uint8 + +const ( + CREATE Action = iota + UPDATE +) + +// Create +func Create(siteid string, title string, description string, published string, + anonAllowed string, apiProductName string, requireCallbackUrl string, imageUrl string, + categoryIds []string, +) (respBody []byte, err error) { + return createOrUpdate(siteid, "", title, description, published, anonAllowed, + apiProductName, requireCallbackUrl, imageUrl, categoryIds, CREATE) +} + +// Update +func Update(siteid string, id string, title string, description string, published string, + anonAllowed string, apiProductName string, requireCallbackUrl string, imageUrl string, + categoryIds []string, +) (respBody []byte, err error) { + return createOrUpdate(siteid, id, title, description, published, anonAllowed, + apiProductName, requireCallbackUrl, imageUrl, categoryIds, UPDATE) +} + +func createOrUpdate(siteid string, id string, title string, description string, published string, + anonAllowed string, apiProductName string, requireCallbackUrl string, imageUrl string, + categoryIds []string, action Action, +) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + + apidoc := []string{} + + apidoc = append(apidoc, "\"siteId\":"+"\""+siteid+"\"") + apidoc = append(apidoc, "\"title\":"+"\""+title+"\"") + apidoc = append(apidoc, "\"apiProductName\":"+"\""+apiProductName+"\"") + + if description != "" { + apidoc = append(apidoc, "\"description\":"+"\""+description+"\"") + } + + if published != "" { + apidoc = append(apidoc, "\"published\":"+published) + } + + if anonAllowed != "" { + apidoc = append(apidoc, "\"anonAllowed\":"+anonAllowed) + } + + if requireCallbackUrl != "" { + apidoc = append(apidoc, "\"requireCallbackUrl\":"+requireCallbackUrl) + } + + if imageUrl != "" { + apidoc = append(apidoc, "\"imageUrl\":"+"\""+imageUrl+"\"") + } + + if len(categoryIds) > 0 { + apidoc = append(apidoc, "\"categoryIds\":[\""+getArrayStr(categoryIds)+"\"]") + } + + payload := "{" + strings.Join(apidoc, ",") + "}" + + if action == CREATE { + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "sites", siteid, "apidocs") + respBody, err = apiclient.HttpClient(u.String(), payload) + } else { + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "sites", siteid, "apidocs", id) + respBody, err = apiclient.HttpClient(u.String(), payload, "PUT") + } + + return respBody, err +} + +// GetDocumentation +func GetDocumentation(siteid string, id string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "sites", siteid, "apidocs", id, "documentation") + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// Get +func Get(siteid string, id string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "sites", siteid, "apidocs", id) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// List +func List(siteid string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "sites", siteid, "apidocs") + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// Delete +func Delete(siteid string, id string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "sites", siteid, "apidocs", id) + respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") + return respBody, err +} + +// UpdateDocumentation +func UpdateDocumentation(siteid string, id string, displayName string, openAPIDoc string, graphQLDoc string, endpointUri string) (respBody []byte, err error) { + var payload string + + if openAPIDoc != "" { + payload = "{\"oasDocumentation\":{\"spec\":{\"displayName\":\"" + + displayName + "\",\"contents\":" + openAPIDoc + "}}}" + } + + if graphQLDoc != "" { + payload = "{\"graphqlDocumentation\":{\"endpointUri\":\"" + endpointUri + + "\",\"schema\":{\"displayName\":\"" + displayName + + "\",\"contents\":" + graphQLDoc + "}}}" + } + + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "sites", siteid, "apidocs", id, "documentation") + respBody, err = apiclient.HttpClient(u.String(), payload, "PATCH") + + return nil, nil +} + +func getArrayStr(str []string) string { + tmp := strings.Join(str, ",") + tmp = strings.ReplaceAll(tmp, ",", "\",\"") + return tmp +} diff --git a/internal/client/datastores/datastores.go b/internal/client/datastores/datastores.go new file mode 100644 index 000000000..57218f710 --- /dev/null +++ b/internal/client/datastores/datastores.go @@ -0,0 +1,222 @@ +// 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 datastores + +import ( + "encoding/json" + "fmt" + "net/url" + "path" + "strings" + + "internal/apiclient" +) + +type axdatastores struct { + Datastores []axdatastore `json:"datastores,omitempty"` +} + +type axdatastore struct { + Self string `json:"self,omitempty"` + DisplayName string `json:"displayName,omitempty"` + Org string `json:"org,omitempty"` + TargetType string `json:"targetType,omitempty"` + CreateTime string `json:"createTime,omitempty"` + LastUpdateTime string `json:"lastUpdateTime,omitempty"` + DatastoreConfig datastoreconfig `json:"datastoreConfig,omitempty"` +} + +type datastoreconfig struct { + ProjectID string `json:"projectId,omitempty"` + BucketName string `json:"bucketName,omitempty"` + Path string `json:"path,omitempty"` + TablePrefix string `json:"tablePrefix,omitempty"` + DatasetName string `json:"datasetName,omitempty"` +} + +type Action uint8 + +const ( + CREATE Action = iota + UPDATE + TEST +) + +// Create +func Create(displayName string, targetType string, projectID string, + bucketName string, gcsPath string, datasetName string, + tablePrefix string, +) (respBody []byte, err error) { + return createOrTestorUpdate("", displayName, targetType, projectID, bucketName, + gcsPath, datasetName, tablePrefix, CREATE) +} + +// Update +func Update(id string, displayName string, targetType string, projectID string, + bucketName string, gcsPath string, datasetName string, + tablePrefix string, +) (respBody []byte, err error) { + return createOrTestorUpdate(id, displayName, targetType, projectID, bucketName, + gcsPath, datasetName, tablePrefix, UPDATE) +} + +// Test +func Test(id string, displayName string, targetType string, projectID string, + bucketName string, gcsPath string, datasetName string, + tablePrefix string, +) (respBody []byte, err error) { + return createOrTestorUpdate(id, displayName, targetType, projectID, bucketName, + gcsPath, datasetName, tablePrefix, TEST) +} + +func createOrTestorUpdate(id string, displayName string, targetType string, projectID string, + bucketName string, gcsPath string, datasetName string, + tablePrefix string, action Action, +) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + + ds := []string{} + + ds = append(ds, "\"displayName\":"+"\""+displayName+"\"") + ds = append(ds, "\"targetType\":"+"\""+targetType+"\"") + + dsc := []string{} + dsc = append(dsc, "\"projectId\":"+"\""+projectID+"\"") + if targetType == "gcs" { + if bucketName == "" || gcsPath == "" { + return nil, fmt.Errorf("bucketName and path are mandatory parameters") + } + dsc = append(dsc, "\"bucketName\":"+"\""+bucketName+"\"") + dsc = append(dsc, "\"path\":"+"\""+gcsPath+"\"") + } else if targetType == "bigquery" { + if datasetName == "" || tablePrefix == "" { + return nil, fmt.Errorf("datasetName and tablePrefix are mandatory parameters") + } + dsc = append(dsc, "\"datasetName\":"+"\""+datasetName+"\"") + dsc = append(dsc, "\"tablePrefix\":"+"\""+tablePrefix+"\"") + } + + dataConfig := "{" + strings.Join(dsc, ",") + "}" + ds = append(ds, "\"datastoreConfig\":"+dataConfig) + + payload := "{" + strings.Join(ds, ",") + "}" + + if action == CREATE { + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "analytics", "datastores") + respBody, err = apiclient.HttpClient(u.String(), payload) + } else if action == UPDATE { + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "analytics", "datastores", id) + respBody, err = apiclient.HttpClient(u.String(), payload, "PUT") + } else if action == TEST { + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "analytics", "datastores:test") + respBody, err = apiclient.HttpClient(u.String(), payload) + } + + return respBody, err +} + +// Delete +func Delete(id string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "analytics", "datastores", id) + respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") + return respBody, err +} + +// Get +func Get(id string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "analytics", "datastores", id) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +func GetName(name string) (respBody []byte, err error) { + apiclient.ClientPrintHttpResponse.Set(false) + defer apiclient.ClientPrintHttpResponse.Set(apiclient.GetCmdPrintHttpResponseSetting()) + listBody, err := List("") + if err != nil { + return nil, err + } + + listDatastores := axdatastores{} + + err = json.Unmarshal(listBody, &listDatastores) + if err != nil { + return nil, err + } + + if len(listDatastores.Datastores) < 1 { + return nil, fmt.Errorf("data store was not found") + } + + for _, ds := range listDatastores.Datastores { + if ds.DisplayName == name { + return json.Marshal(ds) + } + } + return nil, fmt.Errorf("data store was not found") +} + +// GetVersion +func GetVersion(name string) (version string, err error) { + apiclient.ClientPrintHttpResponse.Set(false) + defer apiclient.ClientPrintHttpResponse.Set(apiclient.GetCmdPrintHttpResponseSetting()) + listBody, err := List("") + if err != nil { + return "", err + } + + listDatastores := axdatastores{} + + err = json.Unmarshal(listBody, &listDatastores) + if err != nil { + return "", err + } + + if len(listDatastores.Datastores) < 1 { + return "", fmt.Errorf("data store was not found") + } + + for _, ds := range listDatastores.Datastores { + if ds.DisplayName == name { + return getVersion(ds.Self), nil + } + } + return "", fmt.Errorf("data store was not found") +} + +// List +func List(targetType string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "analytics", "datastores") + if (targetType != "") && (targetType != "gcs" && targetType != "bigquery") { + return nil, fmt.Errorf("invalid targetType. Must be gcs or bigquery") + } + q := u.Query() + if targetType != "" { + q.Set("targetType", targetType) + } + + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// getVersion +func getVersion(name string) (version string) { + s := strings.Split(name, "/") + return s[len(s)-1] +} diff --git a/internal/client/env/env.go b/internal/client/env/env.go index 034b65e46..b57a9e016 100644 --- a/internal/client/env/env.go +++ b/internal/client/env/env.go @@ -241,3 +241,34 @@ func ClearEnvProperties() (err error) { return err } + +// GetSecurityActionsConfig +func GetSecurityActionsConfig() (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "securityActionsConfig") + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// GetSecurityRuntimeConfig +func GetSecurityRuntimeConfig() (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "apiSecurityRuntimeConfig") + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// UpdateSecurityActionsConfig +func UpdateSecurityActionsConfig(action bool) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "apiSecurityRuntimeConfig") + + payload := fmt.Sprintf("{ \"name\": \"organizations/%s/environments/%s/securityActionsConfig\",\"payload\": %t}", + apiclient.GetApigeeOrg(), apiclient.GetApigeeEnv(), action) + + respBody, err = apiclient.HttpClient(u.String(), payload, "PATCH") + return respBody, err +} diff --git a/internal/client/env/securityactions.go b/internal/client/env/securityactions.go new file mode 100644 index 000000000..83ebe0b2c --- /dev/null +++ b/internal/client/env/securityactions.go @@ -0,0 +1,117 @@ +// 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 env + +import ( + "encoding/json" + "net/url" + "path" + "strconv" + + "internal/apiclient" +) + +type securityAction struct { + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + State string `json:"state,omitempty"` + CreateTime string `json:"createTime,omitempty"` + UpdateTime string `json:"updateTime,omitempty"` + ConditionConfig conditionConfig `json:"conditionConfig,omitempty"` + Allow responseCode `json:"allow,omitempty"` + Deny responseCode `json:"deny,omitempty"` + Flag flag `json:"flag,omitempty"` + ExpireTime string `json:"expireTime,omitempty"` + Ttl string `json:"ttl,omitempty"` +} + +type conditionConfig struct { + IpAddressRanges []string `json:"ipAddressRanges,omitempty"` + BotReasons []string `json:"botReasons,omitempty"` +} + +type responseCode struct { + ResponseCode int `json:"responseCode,omitempty"` +} + +type flag struct { + Headers []header `json:"headers,omitempty"` +} + +type header struct { + Name string `json:"name,omitempty"` + Value string `json:"value,omitempty"` +} + +// CreateSecurityAction +func CreateSecurityAction(name string, content []byte) (respBody []byte, err error) { + sa := securityAction{} + if err = json.Unmarshal(content, &sa); err != nil { + return nil, err + } + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "securityActions") + respBody, err = apiclient.HttpClient(u.String(), string(content)) + return respBody, err +} + +// DisableSecurityAction +func DisableSecurityAction(name string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "securityActions", name+":disable") + respBody, err = apiclient.HttpClient(u.String(), "") + return respBody, err +} + +// EnableSecurityAction +func EnableSecurityAction(name string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "securityActions", name+":enable") + respBody, err = apiclient.HttpClient(u.String(), "") + return respBody, err +} + +// GetSecurityAction +func GetSecurityAction(name string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "securityActions", name) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// ListSecurityActions +func ListSecurityActions(pageSize int, pageToken string, filter string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "securityActions") + q := u.Query() + if pageSize != -1 { + q.Set("pageSize", strconv.Itoa(pageSize)) + } + if pageToken != "" { + q.Set("pageToken", pageToken) + } + if filter != "" { + q.Set("filter", filter) + } + + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} diff --git a/internal/client/env/securityincidents.go b/internal/client/env/securityincidents.go new file mode 100644 index 000000000..1087544d4 --- /dev/null +++ b/internal/client/env/securityincidents.go @@ -0,0 +1,53 @@ +// 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 env + +import ( + "net/url" + "path" + "strconv" + + "internal/apiclient" +) + +// GetSecurityIncident +func GetSecurityIncident(name string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "securityIncidents", name) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// ListSecurityIncidents +func ListSecurityIncidents(pageSize int, pageToken string, filter string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "securityIncidents") + q := u.Query() + if pageSize != -1 { + q.Set("pageSize", strconv.Itoa(pageSize)) + } + if pageToken != "" { + q.Set("pageToken", pageToken) + } + if filter != "" { + q.Set("filter", filter) + } + + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} diff --git a/internal/client/env/securityreports.go b/internal/client/env/securityreports.go new file mode 100644 index 000000000..72070080b --- /dev/null +++ b/internal/client/env/securityreports.go @@ -0,0 +1,85 @@ +// 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 env + +import ( + "net/url" + "path" + "strconv" + + "internal/apiclient" +) + +// GetSecurityReportView +func GetSecurityReportView(reportID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "securityReports", reportID, "resultView") + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// GetSecurityReportResult +func GetSecurityReportResult(reportID string, name string) (err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "securityReports", reportID, "result") + err = apiclient.DownloadResource(u.String(), name, ".zip", true) + return err +} + +// GetSecurityReport +func GetSecurityReport(reportID string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "securityReports", reportID) + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// ListSecurityReports +func ListSecurityReports(pageSize int, pageToken string, dataset string, to string, + from string, status string, submittedBy string, +) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "environments", + apiclient.GetApigeeEnv(), "securityReports") + q := u.Query() + if pageSize != -1 { + q.Set("pageSize", strconv.Itoa(pageSize)) + } + if pageToken != "" { + q.Set("pageToken", pageToken) + } + if dataset != "" { + q.Set("dataset", dataset) + } + if to != "" { + q.Set("to", to) + } + if from != "" { + q.Set("from", from) + } + if status != "" { + q.Set("status", status) + } + if submittedBy != "" { + q.Set("submittedBy", submittedBy) + } + + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} diff --git a/internal/client/orgs/orgs.go b/internal/client/orgs/orgs.go index e435e3d59..94ef0d676 100644 --- a/internal/client/orgs/orgs.go +++ b/internal/client/orgs/orgs.go @@ -44,23 +44,28 @@ type orgProperties struct { } type organization struct { - Name string `json:"name,omitempty"` - DisplayName string `json:"displayName,omitempty"` - Description string `json:"description,omitempty"` - CreatedAt string `json:"createdAt,omitempty"` - LastModifiedAt string `json:"lastModifiedAt,omitempty"` - Environments []string `json:"environments,omitempty"` - Properties orgProperties `json:"properties,omitempty"` - AnalyticsRegion string `json:"analyticsRegion,omitempty"` - AuthorizedNetwork string `json:"authorizedNetwork,omitempty"` - RuntimeType string `json:"runtimeType,omitempty"` - SubscriptionType string `json:"subscriptionType,omitempty"` - CaCertificate string `json:"caCertificate,omitempty"` - RuntimeEncryptionKeyName string `json:"runtimeDatabaseEncryptionKeyName,omitempty"` - ProjectId string `json:"projectId,omitempty"` - State string `json:"state,omitempty"` - BillingType string `json:"billingType,omitempty"` - AddOnsConfig addonsConfig `json:"addonsConfig,omitempty"` + Name string `json:"name,omitempty"` + DisplayName string `json:"displayName,omitempty"` + Description string `json:"description,omitempty"` + CreatedAt string `json:"createdAt,omitempty"` + LastModifiedAt string `json:"lastModifiedAt,omitempty"` + Environments []string `json:"environments,omitempty"` + Properties orgProperties `json:"properties,omitempty"` + AnalyticsRegion string `json:"analyticsRegion,omitempty"` + AuthorizedNetwork string `json:"authorizedNetwork,omitempty"` + RuntimeType string `json:"runtimeType,omitempty"` + SubscriptionType string `json:"subscriptionType,omitempty"` + CaCertificate string `json:"caCertificate,omitempty"` + RuntimeEncryptionKeyName string `json:"runtimeDatabaseEncryptionKeyName,omitempty"` + ProjectId string `json:"projectId,omitempty"` + State string `json:"state,omitempty"` + BillingType string `json:"billingType,omitempty"` + AddOnsConfig addonsConfig `json:"addonsConfig,omitempty"` + ApiConsumerDataEncryptionKeyName string `json:"apiConsumerDataEncryptionKeyName,omitempty"` + ControlPlaneEncryptionKeyName string `json:"controlPlaneEncryptionKeyName,omitempty"` + ApiConsumerDataLocation string `json:"apiConsumerDataLocation,omitempty"` + ApigeeProjectId string `json:"apigeeProjectId,omitempty"` + DisableVpcPeering bool `json:"disableVpcPeering,omitempty"` } type addonsConfig struct { @@ -85,11 +90,15 @@ func validRegion(region string) bool { } // Create -func Create(region string, network string, runtimeType string, databaseKey string, billingType string, disablePortal bool) (respBody []byte, err error) { +func Create(description string, analyticsRegion string, authorizedNetwork string, + disableVpcPeering bool, runtimeType string, billingType string, runtimeDatabaseEncryptionKeyName string, + portalDisabled bool, apiConsumerDataEncryptionKeyName string, controlPlaneEncryptionKeyName string, + apiConsumerDataLocation string, +) (respBody []byte, err error) { const baseURL = "https://apigee.googleapis.com/v1/organizations" stageBaseURL := "https://staging-apigee.sandbox.googleapis.com/v1/organizations/" - if !validRegion(region) { + if !validRegion(analyticsRegion) { return respBody, fmt.Errorf("invalid analytics region."+ " Analytics region must be one of : %v", analyticsRegions) } @@ -108,14 +117,38 @@ func Create(region string, network string, runtimeType string, databaseKey strin orgPayload := []string{} orgPayload = append(orgPayload, "\"name\":\""+apiclient.GetApigeeOrg()+"\"") - orgPayload = append(orgPayload, "\"analyticsRegion\":\""+region+"\"") + orgPayload = append(orgPayload, "\"analyticsRegion\":\""+analyticsRegion+"\"") orgPayload = append(orgPayload, "\"runtimeType\":\""+runtimeType+"\"") - if disablePortal { + if description != "" { + orgPayload = append(orgPayload, "\"description\":\""+description+"\"") + } + if portalDisabled { orgPayload = append(orgPayload, "\"portalDisabled\": true") } + if runtimeType == "CLOUD" { - orgPayload = append(orgPayload, "\"authorizedNetwork\":\""+network+"\"") - orgPayload = append(orgPayload, "\"runtimeDatabaseEncryptionKeyName\":\""+databaseKey+"\"") + if disableVpcPeering { + orgPayload = append(orgPayload, "\"disableVpcPeering\": true") + } else if !disableVpcPeering && authorizedNetwork == "" { + return nil, fmt.Errorf("authorizedNetwork must be passed when VPC Peering is disabled") + } else { + orgPayload = append(orgPayload, "\"disableVpcPeering\": false") + orgPayload = append(orgPayload, "\"authorizedNetwork\":\""+authorizedNetwork+"\"") + } + orgPayload = append(orgPayload, "\"runtimeDatabaseEncryptionKeyName\":\""+ + runtimeDatabaseEncryptionKeyName+"\"") + if apiConsumerDataEncryptionKeyName != "" { + orgPayload = append(orgPayload, "\"apiConsumerDataEncryptionKeyName\":\""+ + apiConsumerDataEncryptionKeyName+"\"") + } + if controlPlaneEncryptionKeyName != "" { + orgPayload = append(orgPayload, "\"controlPlaneEncryptionKeyName\":\""+ + controlPlaneEncryptionKeyName+"\"") + } + if apiConsumerDataLocation != "" { + orgPayload = append(orgPayload, "\"apiConsumerDataLocation\":\""+ + apiConsumerDataLocation+"\"") + } } if billingType != "" { @@ -148,6 +181,7 @@ func Delete(retension string) (respBody []byte, err error) { return respBody, err } +// GetOrgField func GetOrgField(key string) (value string, err error) { u, _ := url.Parse(apiclient.BaseURL) u.Path = path.Join(u.Path, apiclient.GetApigeeOrg()) @@ -165,6 +199,39 @@ func GetOrgField(key string) (value string, err error) { return fmt.Sprintf("%v", orgMap[key]), nil } +// GetAddOn +func GetAddOn(addon string) (enabled bool) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg()) + + apiclient.DisableCmdPrintHttpResponse() + defer apiclient.EnableCmdPrintHttpResponse() + + orgBody, err := apiclient.HttpClient(u.String()) + if err != nil { + return false + } + o := organization{} + err = json.Unmarshal(orgBody, &o) + if err != nil { + return false + } + switch addon { + case "advancedApiOpsConfig": + return o.AddOnsConfig.AdvancedApiOpsConfig.Enabled + case "integrationConfig": + return o.AddOnsConfig.IntegrationConfig.Enabled + case "monetizationConfig": + return o.AddOnsConfig.MonetizationConfig.Enabled + case "apiSecurityConfig": + return o.AddOnsConfig.AdvancedApiSecurityConfig.Enabled + case "connectorsPlatformConfig": + return o.AddOnsConfig.ConnectorsPlatformConfig.Enabled + default: + return false + } +} + // List func List() (respBody []byte, err error) { u, _ := url.Parse(apiclient.BaseURL) @@ -273,7 +340,7 @@ func SetOrgProperty(name string, value string) (err error) { } // Update -func Update(description string, displayName string, region string, network string, runtimeType string, databaseKey string) (respBody []byte, err error) { +func Update(description string, authorizedNetwork string) (respBody []byte, err error) { apiclient.ClientPrintHttpResponse.Set(false) orgBody, err := Get() if err != nil { @@ -291,24 +358,8 @@ func Update(description string, displayName string, region string, network strin org.Description = description } - if displayName != "" { - org.DisplayName = displayName - } - - if region != "" { - org.AnalyticsRegion = region - } - - if network != "" { - org.AuthorizedNetwork = network - } - - if runtimeType != "" { - org.RuntimeType = runtimeType - } - - if databaseKey != "" { - org.RuntimeEncryptionKeyName = databaseKey + if authorizedNetwork != "" { + org.AuthorizedNetwork = authorizedNetwork } newOrgBody, err := json.Marshal(org) diff --git a/internal/client/securityprofiles/securityprofiles.go b/internal/client/securityprofiles/securityprofiles.go new file mode 100644 index 000000000..6f080ea45 --- /dev/null +++ b/internal/client/securityprofiles/securityprofiles.go @@ -0,0 +1,270 @@ +// 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 securityprofiles + +import ( + "encoding/json" + "errors" + "fmt" + "net/url" + "path" + "strconv" + "strings" + "sync" + + "internal/apiclient" + "internal/clilog" +) + +type secprofiles struct { + SecurityProfiles []secprofile `json:"securityProfiles,omitempty"` + NextPageToken string `json:"nextPageToken,omitempty"` +} + +type secprofile struct { + Name string `json:"name"` + DisplayName string `json:"displayName"` + Description string `json:"description,omitempty"` + RevisionID string `json:"revisionId,omitempty"` + ProfileConfig profileConfig `json:"profileConfig"` + ScoreConfigs []scoreConfig `json:"scoringConfigs,omitempty"` +} + +type profileConfig struct { + Categories []category `json:"categories"` +} + +type scoreConfig struct { + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` + ScorePath string `json:"scorePath,omitempty"` +} + +type category struct { + Abuse interface{} `json:"abuse,omitempty"` + Mediation interface{} `json:"mediation,omitempty"` + Authorization interface{} `json:"authorization,omitempty"` + Threat interface{} `json:"threat,omitempty"` + Mtls interface{} `json:"mtls,omitempty"` + Cors interface{} `json:"cors,omitempty"` +} + +const maxPageSize = 50 + +// Create +func Create(name string, content []byte) (respBody []byte, err error) { + sc := secprofile{} + if err = json.Unmarshal(content, &sc); err != nil { + return nil, err + } + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "securityProfiles") + q := u.Query() + q.Set("securityProfileId", name) + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String(), string(content)) + return respBody, err +} + +// Attach +func Attach(name string, revision string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "securityProfiles", name, "environments") + attachProfile := []string{} + attachProfile = append(attachProfile, "\"name\":"+"\""+apiclient.GetApigeeEnv()+"\"") + attachProfile = append(attachProfile, "\"securityProfileRevisionId\":"+"\""+revision+"\"") + payload := "{" + strings.Join(attachProfile, ",") + "}" + respBody, err = apiclient.HttpClient(u.String(), payload) + return respBody, err +} + +// Detach +func Detach(name string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "securityProfiles", + name, "environments", apiclient.GetApigeeEnv()) + respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") + return respBody, err +} + +// Delete +func Delete(name string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "securityProfiles", name) + respBody, err = apiclient.HttpClient(u.String(), "", "DELETE") + return respBody, err +} + +// Get +func Get(name string, revision string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + if revision != "" { + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "securityProfiles", name+"@"+revision) + } else { + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "securityProfiles", name) + } + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// ListRevisions +func ListRevisions(name string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "securityProfiles", name+":listRevisions") + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// List +func List(pageSize int, pageToken string) (respBody []byte, err error) { + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "securityProfiles") + q := u.Query() + if pageSize != -1 { + q.Set("pageSize", strconv.Itoa(pageSize)) + } + if pageToken != "" { + q.Set("pageToken", pageToken) + } + + u.RawQuery = q.Encode() + respBody, err = apiclient.HttpClient(u.String()) + return respBody, err +} + +// Update +func Update(name string, content []byte) (respBody []byte, err error) { + sc := secprofile{} + if err = json.Unmarshal(content, &sc); err != nil { + return nil, err + } + u, _ := url.Parse(apiclient.BaseURL) + u.Path = path.Join(u.Path, apiclient.GetApigeeOrg(), "securityProfiles", name) + q := u.Query() + q.Set("updateMask", "description,profileConfig") + u.RawQuery = q.Encode() + + respBody, err = apiclient.HttpClient(u.String(), string(content), "PATCH") + return respBody, err +} + +// Export +func Export(conn int, folder string, allRevisions bool) (err error) { + apiclient.ClientPrintHttpResponse.Set(false) + defer apiclient.ClientPrintHttpResponse.Set(apiclient.GetCmdPrintHttpResponseSetting()) + + pageToken := "" + listsecprofiles := secprofiles{} + + for { + l := secprofiles{} + listRespBytes, err := List(maxPageSize, pageToken) + if err != nil { + return fmt.Errorf("failed to fetch security profiles: %w", err) + } + err = json.Unmarshal(listRespBytes, &l) + if err != nil { + return fmt.Errorf("failed to unmarshall: %w", err) + } + listsecprofiles.SecurityProfiles = append(listsecprofiles.SecurityProfiles, l.SecurityProfiles...) + if l.NextPageToken == "" { + break + } + } + + errChan := make(chan error) + workChan := make(chan secprofile, len(listsecprofiles.SecurityProfiles)) + + fanOutWg := sync.WaitGroup{} + fanInWg := sync.WaitGroup{} + + errs := []string{} + fanInWg.Add(1) + + go func() { + defer fanInWg.Done() + for { + newErr, ok := <-errChan + if !ok { + return + } + errs = append(errs, newErr.Error()) + } + }() + + for i := 0; i < conn; i++ { + fanOutWg.Add(1) + go exportWorker(&fanOutWg, workChan, folder, allRevisions, errChan) + } + + for _, i := range listsecprofiles.SecurityProfiles { + workChan <- i + } + + close(workChan) + fanOutWg.Wait() + close(errChan) + fanInWg.Wait() + + if len(errs) > 0 { + return errors.New(strings.Join(errs, "\n")) + } + + return nil +} + +func exportWorker(wg *sync.WaitGroup, workCh <-chan secprofile, folder string, allRevisions bool, errs chan<- error) { + defer wg.Done() + for { + var respBody []byte + var err error + + listsecprofiles := secprofiles{} + + work, ok := <-workCh + if !ok { + return + } + + if allRevisions { + securityProfileName := work.Name[strings.LastIndex(work.Name, "/")+1:] + clilog.Info.Printf("Exporting all the revisions for Security Profile %s\n", securityProfileName) + + if respBody, err = ListRevisions(securityProfileName); err != nil { + errs <- err + } + err = json.Unmarshal(respBody, &listsecprofiles) + if err != nil { + errs <- err + } + for _, s := range listsecprofiles.SecurityProfiles { + payload, err := json.Marshal(s) + if err != nil { + errs <- err + } + payload, _ = apiclient.PrettifyJSON(payload) + apiclient.WriteByteArrayToFile(path.Join(folder, s.Name), false, payload) + } + } else { + clilog.Info.Printf("Exporting Security Profile %s\n", work.Name) + payload, err := json.Marshal(work) + if err != nil { + errs <- err + } + payload, _ = apiclient.PrettifyJSON(payload) + apiclient.WriteByteArrayToFile(path.Join(folder, work.Name+".json"), false, payload) + } + } +}