pkg/cmd/server/admin/overwrite_bootstrappolicy.go
ad916a82
 package admin
 
 import (
 	"errors"
 	"fmt"
ac38ade6
 	"io"
ad916a82
 
6a7364d3
 	etcdclient "github.com/coreos/go-etcd/etcd"
ad916a82
 	"github.com/spf13/cobra"
 
83c702b4
 	kapi "k8s.io/kubernetes/pkg/api"
 	"k8s.io/kubernetes/pkg/api/meta"
 	"k8s.io/kubernetes/pkg/kubectl"
 	kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
 	"k8s.io/kubernetes/pkg/kubectl/resource"
 	"k8s.io/kubernetes/pkg/runtime"
ad916a82
 
 	"github.com/openshift/origin/pkg/api/latest"
 	authorizationapi "github.com/openshift/origin/pkg/authorization/api"
557f1436
 	policyregistry "github.com/openshift/origin/pkg/authorization/registry/policy"
 	policyetcd "github.com/openshift/origin/pkg/authorization/registry/policy/etcd"
 	policybindingregistry "github.com/openshift/origin/pkg/authorization/registry/policybinding"
 	policybindingetcd "github.com/openshift/origin/pkg/authorization/registry/policybinding/etcd"
ad916a82
 	roleregistry "github.com/openshift/origin/pkg/authorization/registry/role"
89b6ba81
 	rolestorage "github.com/openshift/origin/pkg/authorization/registry/role/policybased"
 	rolebindingstorage "github.com/openshift/origin/pkg/authorization/registry/rolebinding/policybased"
83c702b4
 	"k8s.io/kubernetes/pkg/storage"
 	etcdstorage "k8s.io/kubernetes/pkg/storage/etcd"
ba6a7bc8
 
 	clusterpolicyregistry "github.com/openshift/origin/pkg/authorization/registry/clusterpolicy"
 	clusterpolicyetcd "github.com/openshift/origin/pkg/authorization/registry/clusterpolicy/etcd"
 	clusterpolicybindingregistry "github.com/openshift/origin/pkg/authorization/registry/clusterpolicybinding"
 	clusterpolicybindingetcd "github.com/openshift/origin/pkg/authorization/registry/clusterpolicybinding/etcd"
 	clusterroleregistry "github.com/openshift/origin/pkg/authorization/registry/clusterrole"
 	clusterrolestorage "github.com/openshift/origin/pkg/authorization/registry/clusterrole/proxy"
 	clusterrolebindingstorage "github.com/openshift/origin/pkg/authorization/registry/clusterrolebinding/proxy"
 
ac38ade6
 	"github.com/openshift/origin/pkg/cmd/cli/describe"
ad916a82
 	configapilatest "github.com/openshift/origin/pkg/cmd/server/api/latest"
 	"github.com/openshift/origin/pkg/cmd/server/etcd"
 	cmdclientcmd "github.com/openshift/origin/pkg/cmd/util/clientcmd"
 	templateapi "github.com/openshift/origin/pkg/template/api"
 )
 
28e73694
 const OverwriteBootstrapPolicyCommandName = "overwrite-policy"
 
ad916a82
 type OverwriteBootstrapPolicyOptions struct {
 	File             string
 	MasterConfigFile string
28e73694
 
 	Force                        bool
 	Out                          io.Writer
 	CreateBootstrapPolicyCommand string
ad916a82
 }
 
28e73694
 func NewCommandOverwriteBootstrapPolicy(commandName string, fullName string, createBootstrapPolicyCommand string, out io.Writer) *cobra.Command {
ee70e7d9
 	options := &OverwriteBootstrapPolicyOptions{Out: out}
28e73694
 	options.CreateBootstrapPolicyCommand = createBootstrapPolicyCommand
ad916a82
 
 	cmd := &cobra.Command{
28e73694
 		Use:   commandName,
ee70e7d9
 		Short: "Reset the policy to the default values",
e8ccd07b
 		Run: func(cmd *cobra.Command, args []string) {
ad916a82
 			if err := options.Validate(args); err != nil {
e8ccd07b
 				kcmdutil.CheckErr(kcmdutil.UsageError(cmd, err.Error()))
ad916a82
 			}
 
 			if err := options.OverwriteBootstrapPolicy(); err != nil {
e8ccd07b
 				kcmdutil.CheckErr(err)
ad916a82
 			}
 		},
 	}
 
 	flags := cmd.Flags()
 
ac38ade6
 	flags.BoolVarP(&options.Force, "force", "f", false, "You must confirm you really want to reset your policy. This will delete any custom settings you may have.")
28e73694
 	flags.StringVar(&options.File, "filename", "", "The policy template file containing roles and bindings.  One can be created with '"+createBootstrapPolicyCommand+"'.")
40be29be
 	flags.StringVar(&options.MasterConfigFile, "master-config", "openshift.local.config/master/master-config.yaml", "Location of the master configuration file to run from in order to connect to etcd and directly modify the policy.")
ad916a82
 
ea725ace
 	// autocompletion hints
 	cmd.MarkFlagFilename("filename")
 	cmd.MarkFlagFilename("master-config", "yaml", "yml")
 
ad916a82
 	return cmd
 }
 
 func (o OverwriteBootstrapPolicyOptions) Validate(args []string) error {
 	if len(args) != 0 {
 		return errors.New("no arguments are supported")
 	}
 	if len(o.File) == 0 {
 		return errors.New("filename must be provided")
 	}
 	if len(o.MasterConfigFile) == 0 {
 		return errors.New("master-config must be provided")
 	}
 
 	return nil
 }
 
 func (o OverwriteBootstrapPolicyOptions) OverwriteBootstrapPolicy() error {
 	masterConfig, err := configapilatest.ReadAndResolveMasterConfig(o.MasterConfigFile)
 	if err != nil {
 		return err
 	}
 
6a7364d3
 	// Connect and setup etcd interfaces
 	etcdClient, err := etcd.GetAndTestEtcdClient(masterConfig.EtcdClientInfo)
 	if err != nil {
 		return err
 	}
c76e7b47
 	storage, err := newStorage(etcdClient, masterConfig.EtcdStorageConfig.OpenShiftStorageVersion, masterConfig.EtcdStorageConfig.OpenShiftStoragePrefix)
ad916a82
 	if err != nil {
 		return err
 	}
 
c76e7b47
 	return OverwriteBootstrapPolicy(storage, o.File, o.CreateBootstrapPolicyCommand, o.Force, o.Out)
ad916a82
 }
 
c76e7b47
 func OverwriteBootstrapPolicy(storage storage.Interface, policyFile, createBootstrapPolicyCommand string, change bool, out io.Writer) error {
ac38ade6
 	if !change {
 		fmt.Fprintf(out, "Performing a dry run of policy overwrite:\n\n")
 	}
28e73694
 
ad916a82
 	mapper := cmdclientcmd.ShortcutExpander{kubectl.ShortcutExpander{latest.RESTMapper}}
557f1436
 	typer := kapi.Scheme
ad916a82
 	clientMapper := resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
 		return nil, nil
 	})
 
 	r := resource.NewBuilder(mapper, typer, clientMapper).
ab7d732c
 		FilenameParam(false, policyFile).
ad916a82
 		Flatten().
 		Do()
 
 	if r.Err() != nil {
 		return r.Err()
 	}
 
c76e7b47
 	policyRegistry := policyregistry.NewRegistry(policyetcd.NewStorage(storage))
 	policyBindingRegistry := policybindingregistry.NewRegistry(policybindingetcd.NewStorage(storage))
ba6a7bc8
 
c76e7b47
 	clusterPolicyRegistry := clusterpolicyregistry.NewRegistry(clusterpolicyetcd.NewStorage(storage))
 	clusterPolicyBindingRegistry := clusterpolicybindingregistry.NewRegistry(clusterpolicybindingetcd.NewStorage(storage))
ba6a7bc8
 
89b6ba81
 	roleRegistry := roleregistry.NewRegistry(rolestorage.NewVirtualStorage(policyRegistry))
ba6a7bc8
 	roleBindingStorage := rolebindingstorage.NewVirtualStorage(policyRegistry, policyBindingRegistry, clusterPolicyRegistry, clusterPolicyBindingRegistry)
 	clusterRoleStorage := clusterrolestorage.NewClusterRoleStorage(clusterPolicyRegistry)
 	clusterRoleRegistry := clusterroleregistry.NewRegistry(clusterRoleStorage)
 	clusterRoleBindingStorage := clusterrolebindingstorage.NewClusterRoleBindingStorage(clusterPolicyRegistry, clusterPolicyBindingRegistry)
ad916a82
 
 	return r.Visit(func(info *resource.Info) error {
 		template, ok := info.Object.(*templateapi.Template)
 		if !ok {
28e73694
 			return errors.New("policy must be contained in a template.  One can be created with '" + createBootstrapPolicyCommand + "'.")
ad916a82
 		}
5576aaec
 		runtime.DecodeList(template.Objects, kapi.Scheme)
ad916a82
 
 		for _, item := range template.Objects {
ac38ade6
 			switch t := item.(type) {
ad916a82
 			case *authorizationapi.Role:
557f1436
 				ctx := kapi.WithNamespace(kapi.NewContext(), t.Namespace)
ac38ade6
 				if change {
 					roleRegistry.DeleteRole(ctx, t.Name)
89b6ba81
 					if _, err := roleRegistry.CreateRole(ctx, t); err != nil {
ac38ade6
 						return err
 					}
 				} else {
 					fmt.Fprintf(out, "Overwrite role %s/%s\n", t.Namespace, t.Name)
 					if s, err := describe.DescribeRole(t); err == nil {
 						fmt.Fprintf(out, "%s\n", s)
 					}
ad916a82
 				}
 			case *authorizationapi.RoleBinding:
557f1436
 				ctx := kapi.WithNamespace(kapi.NewContext(), t.Namespace)
ac38ade6
 				if change {
89b6ba81
 					roleBindingStorage.Delete(ctx, t.Name, nil)
 					if _, err := roleBindingStorage.CreateRoleBindingWithEscalation(ctx, t); err != nil {
ac38ade6
 						return err
 					}
 				} else {
 					fmt.Fprintf(out, "Overwrite role binding %s/%s\n", t.Namespace, t.Name)
 					if s, err := describe.DescribeRoleBinding(t, nil, nil); err == nil {
 						fmt.Fprintf(out, "%s\n", s)
 					}
ad916a82
 				}
 
ba6a7bc8
 			case *authorizationapi.ClusterRole:
 				ctx := kapi.WithNamespace(kapi.NewContext(), t.Namespace)
 				if change {
 					clusterRoleRegistry.DeleteClusterRole(ctx, t.Name)
 					if _, err := clusterRoleRegistry.CreateClusterRole(ctx, t); err != nil {
 						return err
 					}
 				} else {
 					fmt.Fprintf(out, "Overwrite role %s/%s\n", t.Namespace, t.Name)
 					if s, err := describe.DescribeRole(authorizationapi.ToRole(t)); err == nil {
 						fmt.Fprintf(out, "%s\n", s)
 					}
 				}
 			case *authorizationapi.ClusterRoleBinding:
 				ctx := kapi.WithNamespace(kapi.NewContext(), t.Namespace)
 				if change {
 					clusterRoleBindingStorage.Delete(ctx, t.Name, nil)
 					if _, err := clusterRoleBindingStorage.CreateClusterRoleBindingWithEscalation(ctx, t); err != nil {
 						return err
 					}
 				} else {
 					fmt.Fprintf(out, "Overwrite role binding %s/%s\n", t.Namespace, t.Name)
 					if s, err := describe.DescribeRoleBinding(authorizationapi.ToRoleBinding(t), nil, nil); err == nil {
 						fmt.Fprintf(out, "%s\n", s)
 					}
 				}
 
ad916a82
 			default:
 				return errors.New("only roles and rolebindings may be created in this mode")
 			}
 		}
ac38ade6
 		if !change {
 			fmt.Fprintf(out, "To make the changes described above, pass --force\n")
 		}
ad916a82
 		return nil
 	})
 }
6a7364d3
 
c76e7b47
 // newStorage returns an EtcdHelper for the provided storage version.
 func newStorage(client *etcdclient.Client, version, prefix string) (oshelper storage.Interface, err error) {
6a7364d3
 	interfaces, err := latest.InterfacesFor(version)
 	if err != nil {
c76e7b47
 		return nil, err
6a7364d3
 	}
c76e7b47
 	return etcdstorage.NewEtcdStorage(client, interfaces.Codec, prefix), nil
6a7364d3
 }