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))
                                }
                        }

Reply via email to