This is an automated email from the ASF dual-hosted git repository. astefanutti pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 748accde000393d3d33e0d40f0ea7e11e4ff65ec Author: Nicola Ferraro <[email protected]> AuthorDate: Mon Feb 10 17:53:56 2020 +0100 Fix #1223: checking permissions before install --- pkg/cmd/install.go | 15 +++++++++- pkg/util/olm/operator.go | 77 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go index 292c9d9..eee8a8f 100644 --- a/pkg/cmd/install.go +++ b/pkg/cmd/install.go @@ -19,6 +19,7 @@ package cmd import ( "fmt" + "os" "regexp" "strings" "time" @@ -172,10 +173,22 @@ func (o *installCmdOptions) install(cobraCmd *cobra.Command, _ []string) error { if olmClient, err = clientProvider.Get(); err != nil { return err } - if installViaOLM, err = olm.IsAvailable(o.Context, olmClient, o.Namespace); err != nil { + var olmAvailable bool + if olmAvailable, err = olm.IsAvailable(o.Context, olmClient, o.Namespace); err != nil { return errors.Wrap(err, "error while checking OLM availability. Run with '--olm=false' to skip this check") } + if olmAvailable { + if installViaOLM, err = olm.HasPermissionToInstall(o.Context, olmClient, o.Namespace, o.Global, o.olmOptions); err != nil { + return errors.Wrap(err, "error while checking permissions to install operator via OLM. Run with '--olm=false' to skip this check") + } + if !installViaOLM { + fmt.Fprintln(cobraCmd.OutOrStdout(), "OLM is available but current user has not enough permissions to create the operator. " + + "You can either ask your administrator to provide permissions (preferred) or run the install command with the `--olm=false` flag.") + os.Exit(1) + } + } + if installViaOLM { fmt.Fprintln(cobraCmd.OutOrStdout(), "OLM is available in the cluster") var installed bool diff --git a/pkg/util/olm/operator.go b/pkg/util/olm/operator.go index 5b23d14..73a84e4 100644 --- a/pkg/util/olm/operator.go +++ b/pkg/util/olm/operator.go @@ -27,6 +27,8 @@ import ( olmv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1" olmv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1" "github.com/pkg/errors" + authorizationv1 "k8s.io/api/authorization/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -85,6 +87,79 @@ func IsOperatorInstalled(ctx context.Context, client client.Client, namespace st return false, nil } +// HasPermissionToInstall checks if the current user/serviceaccount has the right permissions to install camel k via OLM +func HasPermissionToInstall(ctx context.Context, client client.Client, namespace string, global bool, options Options) (bool, error) { + if ok, err := checkPermission(client, olmv1alpha1.GroupName, "clusterserviceversions", namespace, options.Package, "list"); err != nil { + return false, err + } else if !ok { + return false, nil + } + + targetNamespace := namespace + if global { + targetNamespace = options.GlobalNamespace + } + + if ok, err := checkPermission(client, olmv1alpha1.GroupName, "subscriptions", targetNamespace, options.Package, "create"); err != nil { + return false, err + } else if !ok { + return false, nil + } + + if installed, err := IsOperatorInstalled(ctx, client, namespace, global, options); err != nil { + return false, err + } else if installed { + return true, nil + } + + if !global { + if ok, err := checkPermission(client, olmv1.GroupName, "operatorgroups", namespace, options.Package, "list"); err != nil { + return false, err + } else if !ok { + return false, nil + } + + group, err := findOperatorGroup(ctx, client, namespace, options) + if err != nil { + return false, err + } + if group == nil { + if ok, err := checkPermission(client, olmv1.GroupName, "operatorgroups", namespace, options.Package, "create"); err != nil { + return false, err + } else if !ok { + return false, nil + } + } + + } + return true, nil +} + +func checkPermission(client client.Client, group, resource, namespace, name, verb string) (bool, error) { + sarReview := &authorizationv1.SelfSubjectAccessReview{ + Spec: authorizationv1.SelfSubjectAccessReviewSpec{ + ResourceAttributes: &authorizationv1.ResourceAttributes{ + Group: group, + Resource: resource, + Namespace: namespace, + Name: name, + Verb: verb, + }, + }, + } + + sar, err := client.AuthorizationV1().SelfSubjectAccessReviews().Create(sarReview) + if err != nil { + if k8serrors.IsForbidden(err) { + return false, nil + } + return false, err + } else if !sar.Status.Allowed { + return false, nil + } + return true, nil +} + // Install creates a subscription for the OLM package func Install(ctx context.Context, client client.Client, namespace string, global bool, options Options, collection *kubernetes.Collection) (bool, error) { options = fillDefaults(options) @@ -141,7 +216,7 @@ func Install(ctx context.Context, client client.Client, namespace string, global collection.Add(group) } else { if err := client.Create(ctx, group); err != nil { - return false, errors.Wrap(err, fmt.Sprintf("namespace %s has no operator group defined and current user is not able to create it. " + + return false, errors.Wrap(err, fmt.Sprintf("namespace %s has no operator group defined and current user is not able to create it. "+ "Make sure you have the right roles to install operators from OLM", namespace)) } }
