func (m *VirtualStorage) confirmNoEscalation(ctx kapi.Context, roleBinding *authorizationapi.RoleBinding) error { modifyingRole, err := m.getReferencedRole(roleBinding.RoleRef) if err != nil { return err } ruleResolver := rulevalidation.NewDefaultRuleResolver( m.PolicyRegistry, m.BindingRegistry, m.ClusterPolicyRegistry, m.ClusterPolicyBindingRegistry, ) ownerLocalRules, err := ruleResolver.GetEffectivePolicyRules(ctx) if err != nil { return kapierrors.NewInternalError(err) } masterContext := kapi.WithNamespace(ctx, "") ownerGlobalRules, err := ruleResolver.GetEffectivePolicyRules(masterContext) if err != nil { return kapierrors.NewInternalError(err) } ownerRules := make([]authorizationapi.PolicyRule, 0, len(ownerGlobalRules)+len(ownerLocalRules)) ownerRules = append(ownerRules, ownerLocalRules...) ownerRules = append(ownerRules, ownerGlobalRules...) ownerRightsCover, missingRights := rulevalidation.Covers(ownerRules, modifyingRole.Rules) if !ownerRightsCover { user, _ := kapi.UserFrom(ctx) return kapierrors.NewUnauthorized(fmt.Sprintf("attempt to grant extra privileges: %v user=%v ownerrules=%v", missingRights, user, ownerRules)) } return nil }
func makeClusterTestStorage() rolebindingregistry.Storage { clusterBindingRegistry := test.NewClusterPolicyBindingRegistry(testNewClusterBindings(), nil) clusterPolicyRegistry := test.NewClusterPolicyRegistry(testNewClusterPolicies(), nil) bindingRegistry := clusterpolicybindingregistry.NewSimulatedRegistry(clusterBindingRegistry) return NewVirtualStorage(bindingRegistry, rulevalidation.NewDefaultRuleResolver(nil, nil, clusterPolicyRegistry, clusterBindingRegistry)) }
func makeTestStorage() rolebindingregistry.Storage { clusterBindingRegistry := test.NewClusterPolicyBindingRegistry(testNewClusterBindings(), nil) bindingRegistry := test.NewPolicyBindingRegistry(testNewLocalBindings(), nil) clusterPolicyRegistry := test.NewClusterPolicyRegistry(testNewClusterPolicies(), nil) policyRegistry := test.NewPolicyRegistry([]authorizationapi.Policy{}, nil) return NewVirtualStorage(bindingRegistry, rulevalidation.NewDefaultRuleResolver(policyRegistry, bindingRegistry, clusterPolicyRegistry, clusterBindingRegistry)) }
func newAuthorizer(policyClient policyclient.ReadOnlyPolicyClient, projectRequestDenyMessage string) authorizer.Authorizer { authorizer := authorizer.NewAuthorizer(rulevalidation.NewDefaultRuleResolver( rulevalidation.PolicyGetter(policyClient), rulevalidation.BindingLister(policyClient), rulevalidation.ClusterPolicyGetter(policyClient), rulevalidation.ClusterBindingLister(policyClient), ), authorizer.NewForbiddenMessageResolver(projectRequestDenyMessage)) return authorizer }
func TestDeleteError(t *testing.T) { bindingRegistry := &test.PolicyBindingRegistry{} bindingRegistry.Err = errors.New("Sample Error") storage := NewVirtualStorage(bindingRegistry, rulevalidation.NewDefaultRuleResolver(&test.PolicyRegistry{}, bindingRegistry, &test.ClusterPolicyRegistry{}, &test.ClusterPolicyBindingRegistry{})) ctx := kapi.WithUser(kapi.WithNamespace(kapi.NewContext(), "unittest"), &user.DefaultInfo{Name: "system:admin"}) _, err := storage.Delete(ctx, "foo", nil) if err != bindingRegistry.Err { t.Errorf("unexpected error: %v", err) } }
func (test *subjectsTest) test(t *testing.T) { policyRegistry := testpolicyregistry.NewPolicyRegistry(test.policies, test.policyRetrievalError) policyBindingRegistry := testpolicyregistry.NewPolicyBindingRegistry(test.bindings, test.bindingRetrievalError) clusterPolicyRegistry := testpolicyregistry.NewClusterPolicyRegistry(test.clusterPolicies, test.policyRetrievalError) clusterPolicyBindingRegistry := testpolicyregistry.NewClusterPolicyBindingRegistry(test.clusterBindings, test.bindingRetrievalError) authorizer := NewAuthorizer(rulevalidation.NewDefaultRuleResolver(policyRegistry, policyBindingRegistry, clusterPolicyRegistry, clusterPolicyBindingRegistry), NewForbiddenMessageResolver("")) actualUsers, actualGroups, actualError := authorizer.GetAllowedSubjects(test.context, *test.attributes) matchStringSlice(test.expectedUsers.List(), actualUsers.List(), "users", t) matchStringSlice(test.expectedGroups.List(), actualGroups.List(), "groups", t) matchError(test.expectedError, actualError, "error", t) }
func (test *authorizeTest) test(t *testing.T) { policyRegistry := testpolicyregistry.NewPolicyRegistry(test.policies, test.policyRetrievalError) policyBindingRegistry := testpolicyregistry.NewPolicyBindingRegistry(test.bindings, test.bindingRetrievalError) clusterPolicyRegistry := testpolicyregistry.NewClusterPolicyRegistry(test.clusterPolicies, test.policyRetrievalError) clusterPolicyBindingRegistry := testpolicyregistry.NewClusterPolicyBindingRegistry(test.clusterBindings, test.bindingRetrievalError) authorizer := NewAuthorizer(rulevalidation.NewDefaultRuleResolver(policyRegistry, policyBindingRegistry, clusterPolicyRegistry, clusterPolicyBindingRegistry), NewForbiddenMessageResolver("")) actualAllowed, actualReason, actualError := authorizer.Authorize(test.context, *test.attributes) matchBool(test.expectedAllowed, actualAllowed, "allowed", t) if actualAllowed { containsString(test.expectedReason, actualReason, "allowReason", t) } else { containsString(test.expectedReason, actualReason, "denyReason", t) matchError(test.expectedError, actualError, "error", t) } }
func NewClusterRoleStorage(clusterPolicyRegistry clusterpolicyregistry.Registry, clusterBindingRegistry clusterpolicybindingregistry.Registry) *ClusterRoleStorage { simulatedPolicyRegistry := clusterpolicyregistry.NewSimulatedRegistry(clusterPolicyRegistry) ruleResolver := rulevalidation.NewDefaultRuleResolver( nil, nil, clusterpolicyregistry.ReadOnlyClusterPolicy{Registry: clusterPolicyRegistry}, clusterpolicybindingregistry.ReadOnlyClusterPolicyBinding{Registry: clusterBindingRegistry}, ) return &ClusterRoleStorage{ roleStorage: rolestorage.VirtualStorage{ PolicyStorage: simulatedPolicyRegistry, RuleResolver: ruleResolver, CreateStrategy: roleregistry.ClusterStrategy, UpdateStrategy: roleregistry.ClusterStrategy}, } }
func NewClusterRoleBindingStorage(clusterPolicyRegistry clusterpolicyregistry.Registry, clusterPolicyBindingRegistry clusterpolicybindingregistry.Registry) *ClusterRoleBindingStorage { simulatedPolicyRegistry := clusterpolicyregistry.NewSimulatedRegistry(clusterPolicyRegistry) simulatedPolicyBindingRegistry := clusterpolicybindingregistry.NewSimulatedRegistry(clusterPolicyBindingRegistry) ruleResolver := rulevalidation.NewDefaultRuleResolver( simulatedPolicyRegistry, simulatedPolicyBindingRegistry, clusterPolicyRegistry, clusterPolicyBindingRegistry, ) return &ClusterRoleBindingStorage{ rolebindingstorage.VirtualStorage{ BindingRegistry: simulatedPolicyBindingRegistry, RuleResolver: ruleResolver, CreateStrategy: rolebindingregistry.ClusterStrategy, UpdateStrategy: rolebindingregistry.ClusterStrategy, }, } }
func NewClusterRoleBindingStorage(clusterPolicyRegistry clusterpolicyregistry.Registry, clusterPolicyBindingRegistry clusterpolicybindingregistry.Registry, cachedRuleResolver rulevalidation.AuthorizationRuleResolver) *ClusterRoleBindingStorage { simulatedPolicyBindingRegistry := clusterpolicybindingregistry.NewSimulatedRegistry(clusterPolicyBindingRegistry) ruleResolver := rulevalidation.NewDefaultRuleResolver( nil, nil, clusterpolicyregistry.ReadOnlyClusterPolicy{Registry: clusterPolicyRegistry}, clusterpolicybindingregistry.ReadOnlyClusterPolicyBinding{Registry: clusterPolicyBindingRegistry}, ) return &ClusterRoleBindingStorage{ rolebindingstorage.VirtualStorage{ BindingRegistry: simulatedPolicyBindingRegistry, RuleResolver: ruleResolver, CachedRuleResolver: cachedRuleResolver, CreateStrategy: rolebindingregistry.ClusterStrategy, UpdateStrategy: rolebindingregistry.ClusterStrategy, Resource: authorizationapi.Resource("clusterrolebinding"), }, } }
// BuildMasterConfig builds and returns the OpenShift master configuration based on the // provided options func BuildMasterConfig(options configapi.MasterConfig) (*MasterConfig, error) { client, err := etcd.EtcdClient(options.EtcdClientInfo) if err != nil { return nil, err } etcdClient, err := etcd.MakeNewEtcdClient(options.EtcdClientInfo) if err != nil { return nil, err } groupVersion := unversioned.GroupVersion{Group: "", Version: options.EtcdStorageConfig.OpenShiftStorageVersion} etcdHelper, err := NewEtcdStorage(etcdClient, groupVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix) if err != nil { return nil, fmt.Errorf("Error setting up server storage: %v", err) } restOptsGetter := restoptions.NewConfigGetter(options) clientCAs, err := configapi.GetClientCertCAPool(options) if err != nil { return nil, err } apiClientCAs, err := configapi.GetAPIClientCertCAPool(options) if err != nil { return nil, err } privilegedLoopbackKubeClient, _, err := configapi.GetKubeClient(options.MasterClients.OpenShiftLoopbackKubeConfig) if err != nil { return nil, err } privilegedLoopbackOpenShiftClient, privilegedLoopbackClientConfig, err := configapi.GetOpenShiftClient(options.MasterClients.OpenShiftLoopbackKubeConfig) if err != nil { return nil, err } customListerWatchers := shared.DefaultListerWatcherOverrides{} if err := addAuthorizationListerWatchers(customListerWatchers, restOptsGetter); err != nil { return nil, err } informerFactory := shared.NewInformerFactory(privilegedLoopbackKubeClient, privilegedLoopbackOpenShiftClient, customListerWatchers, 10*time.Minute) imageTemplate := variable.NewDefaultImageTemplate() imageTemplate.Format = options.ImageConfig.Format imageTemplate.Latest = options.ImageConfig.Latest requestContextMapper := kapi.NewRequestContextMapper() groupStorage, err := groupstorage.NewREST(restOptsGetter) if err != nil { return nil, err } groupCache := usercache.NewGroupCache(groupregistry.NewRegistry(groupStorage)) projectCache := projectcache.NewProjectCache(privilegedLoopbackKubeClient.Namespaces(), options.ProjectConfig.DefaultNodeSelector) clusterQuotaMappingController := clusterquotamapping.NewClusterQuotaMappingController(informerFactory.Namespaces(), informerFactory.ClusterResourceQuotas()) kubeletClientConfig := configapi.GetKubeletClientConfig(options) // in-order list of plug-ins that should intercept admission decisions (origin only intercepts) admissionControlPluginNames := []string{ "ProjectRequestLimit", "OriginNamespaceLifecycle", "PodNodeConstraints", "JenkinsBootstrapper", "BuildByStrategy", imageadmission.PluginName, quotaadmission.PluginName, } if len(options.AdmissionConfig.PluginOrderOverride) > 0 { admissionControlPluginNames = options.AdmissionConfig.PluginOrderOverride } quotaRegistry := quota.NewOriginQuotaRegistry(privilegedLoopbackOpenShiftClient) ruleResolver := rulevalidation.NewDefaultRuleResolver( informerFactory.Policies().Lister(), informerFactory.PolicyBindings().Lister(), informerFactory.ClusterPolicies().Lister().ClusterPolicies(), informerFactory.ClusterPolicyBindings().Lister().ClusterPolicyBindings(), ) authorizer := newAuthorizer(ruleResolver, informerFactory, options.ProjectConfig.ProjectRequestMessage) pluginInitializer := oadmission.PluginInitializer{ OpenshiftClient: privilegedLoopbackOpenShiftClient, ProjectCache: projectCache, OriginQuotaRegistry: quotaRegistry, Authorizer: authorizer, JenkinsPipelineConfig: options.JenkinsPipelineConfig, RESTClientConfig: *privilegedLoopbackClientConfig, } plugins := []admission.Interface{} clientsetClient := clientadapter.FromUnversionedClient(privilegedLoopbackKubeClient) for _, pluginName := range admissionControlPluginNames { configFile, err := pluginconfig.GetPluginConfig(options.AdmissionConfig.PluginConfig[pluginName]) if err != nil { return nil, err } plugin := admission.InitPlugin(pluginName, clientsetClient, configFile) if plugin != nil { plugins = append(plugins, plugin) } } pluginInitializer.Initialize(plugins) // ensure that plugins have been properly initialized if err := oadmission.Validate(plugins); err != nil { return nil, err } admissionController := admission.NewChainHandler(plugins...) // TODO: look up storage by resource serviceAccountTokenGetter, err := newServiceAccountTokenGetter(options, etcdClient) if err != nil { return nil, err } authenticator, err := newAuthenticator(options, restOptsGetter, serviceAccountTokenGetter, apiClientCAs, groupCache) if err != nil { return nil, err } plug, plugStart := newControllerPlug(options, client) config := &MasterConfig{ Options: options, RESTOptionsGetter: restOptsGetter, RuleResolver: ruleResolver, Authenticator: authenticator, Authorizer: authorizer, AuthorizationAttributeBuilder: newAuthorizationAttributeBuilder(requestContextMapper), GroupCache: groupCache, ProjectAuthorizationCache: newProjectAuthorizationCache(authorizer, privilegedLoopbackKubeClient, informerFactory), ProjectCache: projectCache, ClusterQuotaMappingController: clusterQuotaMappingController, RequestContextMapper: requestContextMapper, AdmissionControl: admissionController, TLS: configapi.UseTLS(options.ServingInfo.ServingInfo), ControllerPlug: plug, ControllerPlugStart: plugStart, ImageFor: imageTemplate.ExpandOrDie, EtcdHelper: etcdHelper, KubeletClientConfig: kubeletClientConfig, ClientCAs: clientCAs, APIClientCAs: apiClientCAs, PluginInitializer: pluginInitializer, PrivilegedLoopbackClientConfig: *privilegedLoopbackClientConfig, PrivilegedLoopbackOpenShiftClient: privilegedLoopbackOpenShiftClient, PrivilegedLoopbackKubernetesClient: privilegedLoopbackKubeClient, Informers: informerFactory, } return config, nil }
func makeClusterTestStorage() roleregistry.Storage { clusterPolicyRegistry := test.NewClusterPolicyRegistry(testNewClusterPolicies(), nil) policyRegistry := clusterpolicyregistry.NewSimulatedRegistry(clusterPolicyRegistry) return NewVirtualStorage(policyRegistry, rulevalidation.NewDefaultRuleResolver(nil, &test.PolicyBindingRegistry{}, clusterPolicyRegistry, &test.ClusterPolicyBindingRegistry{}), nil, authorizationapi.Resource("clusterrole")) }
// BuildMasterConfig builds and returns the OpenShift master configuration based on the // provided options func BuildMasterConfig(options configapi.MasterConfig) (*MasterConfig, error) { client, err := etcd.EtcdClient(options.EtcdClientInfo) if err != nil { return nil, err } etcdClient, err := etcd.MakeNewEtcdClient(options.EtcdClientInfo) if err != nil { return nil, err } groupVersion := unversioned.GroupVersion{Group: "", Version: options.EtcdStorageConfig.OpenShiftStorageVersion} etcdHelper, err := NewEtcdStorage(etcdClient, groupVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix) if err != nil { return nil, fmt.Errorf("Error setting up server storage: %v", err) } restOptsGetter := restoptions.NewConfigGetter(options) clientCAs, err := configapi.GetClientCertCAPool(options) if err != nil { return nil, err } apiClientCAs, err := configapi.GetAPIClientCertCAPool(options) if err != nil { return nil, err } privilegedLoopbackKubeClient, _, err := configapi.GetKubeClient(options.MasterClients.OpenShiftLoopbackKubeConfig) if err != nil { return nil, err } privilegedLoopbackOpenShiftClient, privilegedLoopbackClientConfig, err := configapi.GetOpenShiftClient(options.MasterClients.OpenShiftLoopbackKubeConfig) if err != nil { return nil, err } customListerWatchers := shared.DefaultListerWatcherOverrides{} if err := addAuthorizationListerWatchers(customListerWatchers, restOptsGetter); err != nil { return nil, err } informerFactory := shared.NewInformerFactory(privilegedLoopbackKubeClient, privilegedLoopbackOpenShiftClient, customListerWatchers, 10*time.Minute) imageTemplate := variable.NewDefaultImageTemplate() imageTemplate.Format = options.ImageConfig.Format imageTemplate.Latest = options.ImageConfig.Latest requestContextMapper := kapi.NewRequestContextMapper() groupStorage, err := groupstorage.NewREST(restOptsGetter) if err != nil { return nil, err } groupCache := usercache.NewGroupCache(groupregistry.NewRegistry(groupStorage)) projectCache := projectcache.NewProjectCache(privilegedLoopbackKubeClient.Namespaces(), options.ProjectConfig.DefaultNodeSelector) clusterQuotaMappingController := clusterquotamapping.NewClusterQuotaMappingController(informerFactory.Namespaces(), informerFactory.ClusterResourceQuotas()) kubeletClientConfig := configapi.GetKubeletClientConfig(options) kubeClientSet := clientadapter.FromUnversionedClient(privilegedLoopbackKubeClient) quotaRegistry := quota.NewAllResourceQuotaRegistry(privilegedLoopbackOpenShiftClient, kubeClientSet) ruleResolver := rulevalidation.NewDefaultRuleResolver( informerFactory.Policies().Lister(), informerFactory.PolicyBindings().Lister(), informerFactory.ClusterPolicies().Lister().ClusterPolicies(), informerFactory.ClusterPolicyBindings().Lister().ClusterPolicyBindings(), ) authorizer := newAuthorizer(ruleResolver, informerFactory, options.ProjectConfig.ProjectRequestMessage) pluginInitializer := oadmission.PluginInitializer{ OpenshiftClient: privilegedLoopbackOpenShiftClient, ProjectCache: projectCache, OriginQuotaRegistry: quotaRegistry, Authorizer: authorizer, JenkinsPipelineConfig: options.JenkinsPipelineConfig, RESTClientConfig: *privilegedLoopbackClientConfig, Informers: informerFactory, ClusterQuotaMapper: clusterQuotaMappingController.GetClusterQuotaMapper(), } originAdmission, kubeAdmission, err := buildAdmissionChains(options, kubeClientSet, pluginInitializer) // TODO: look up storage by resource serviceAccountTokenGetter, err := newServiceAccountTokenGetter(options, etcdClient) if err != nil { return nil, err } authenticator, err := newAuthenticator(options, restOptsGetter, serviceAccountTokenGetter, apiClientCAs, groupCache) if err != nil { return nil, err } plug, plugStart := newControllerPlug(options, client) config := &MasterConfig{ Options: options, RESTOptionsGetter: restOptsGetter, RuleResolver: ruleResolver, Authenticator: authenticator, Authorizer: authorizer, AuthorizationAttributeBuilder: newAuthorizationAttributeBuilder(requestContextMapper), GroupCache: groupCache, ProjectAuthorizationCache: newProjectAuthorizationCache(authorizer, privilegedLoopbackKubeClient, informerFactory), ProjectCache: projectCache, ClusterQuotaMappingController: clusterQuotaMappingController, RequestContextMapper: requestContextMapper, AdmissionControl: originAdmission, KubeAdmissionControl: kubeAdmission, TLS: configapi.UseTLS(options.ServingInfo.ServingInfo), ControllerPlug: plug, ControllerPlugStart: plugStart, ImageFor: imageTemplate.ExpandOrDie, EtcdHelper: etcdHelper, KubeletClientConfig: kubeletClientConfig, ClientCAs: clientCAs, APIClientCAs: apiClientCAs, PrivilegedLoopbackClientConfig: *privilegedLoopbackClientConfig, PrivilegedLoopbackOpenShiftClient: privilegedLoopbackOpenShiftClient, PrivilegedLoopbackKubernetesClient: privilegedLoopbackKubeClient, Informers: informerFactory, } return config, nil }
func OverwriteBootstrapPolicy(optsGetter restoptions.Getter, policyFile, createBootstrapPolicyCommand string, change bool, out io.Writer) error { if !change { fmt.Fprintf(out, "Performing a dry run of policy overwrite:\n\n") } mapper := cmdclientcmd.ShortcutExpander{RESTMapper: kubectl.ShortcutExpander{RESTMapper: registered.RESTMapper()}} typer := kapi.Scheme clientMapper := resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) { return nil, nil }) r := resource.NewBuilder(mapper, typer, clientMapper, kapi.Codecs.UniversalDecoder()). FilenameParam(false, false, policyFile). Flatten(). Do() if r.Err() != nil { return r.Err() } policyStorage, err := policyetcd.NewStorage(optsGetter) if err != nil { return err } policyRegistry := policyregistry.NewRegistry(policyStorage) policyBindingStorage, err := policybindingetcd.NewStorage(optsGetter) if err != nil { return err } policyBindingRegistry := policybindingregistry.NewRegistry(policyBindingStorage) clusterPolicyStorage, err := clusterpolicyetcd.NewStorage(optsGetter) if err != nil { return err } clusterPolicyRegistry := clusterpolicyregistry.NewRegistry(clusterPolicyStorage) clusterPolicyBindingStorage, err := clusterpolicybindingetcd.NewStorage(optsGetter) if err != nil { return err } clusterPolicyBindingRegistry := clusterpolicybindingregistry.NewRegistry(clusterPolicyBindingStorage) ruleResolver := rulevalidation.NewDefaultRuleResolver( policyListerNamespacer{registry: policyRegistry}, policyBindingListerNamespacer{registry: policyBindingRegistry}, clusterpolicyregistry.ReadOnlyClusterPolicy{Registry: clusterPolicyRegistry}, clusterpolicybindingregistry.ReadOnlyClusterPolicyBinding{Registry: clusterPolicyBindingRegistry}, ) roleStorage := rolestorage.NewVirtualStorage(policyRegistry, ruleResolver, nil, authorizationapi.Resource("role")) roleBindingStorage := rolebindingstorage.NewVirtualStorage(policyBindingRegistry, ruleResolver, nil, authorizationapi.Resource("rolebinding")) clusterRoleStorage := clusterrolestorage.NewClusterRoleStorage(clusterPolicyRegistry, clusterPolicyBindingRegistry, nil) clusterRoleBindingStorage := clusterrolebindingstorage.NewClusterRoleBindingStorage(clusterPolicyRegistry, clusterPolicyBindingRegistry, nil) return r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } template, ok := info.Object.(*templateapi.Template) if !ok { return errors.New("policy must be contained in a template. One can be created with '" + createBootstrapPolicyCommand + "'.") } runtime.DecodeList(template.Objects, kapi.Codecs.UniversalDecoder()) // For each object, we attempt the following to maximize our ability to persist the desired objects, while minimizing etcd write thrashing: // 1. Create the object (no-ops if the object already exists) // 2. If the object already exists, attempt to update the object (no-ops if an identical object is already persisted) // 3. If we encounter any error updating, delete and recreate errs := []error{} for _, item := range template.Objects { switch t := item.(type) { case *authorizationapi.Role: ctx := kapi.WithNamespace(kapi.NewContext(), t.Namespace) if change { // Attempt to create _, err := roleStorage.CreateRoleWithEscalation(ctx, t) // Unconditional replace if it already exists if kapierrors.IsAlreadyExists(err) { _, _, err = roleStorage.UpdateRoleWithEscalation(ctx, t) } // Delete and recreate as a last resort if err != nil { roleStorage.Delete(ctx, t.Name, nil) _, err = roleStorage.CreateRoleWithEscalation(ctx, t) } // Gather any error if err != nil { errs = append(errs, 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) } } case *authorizationapi.RoleBinding: ctx := kapi.WithNamespace(kapi.NewContext(), t.Namespace) if change { // Attempt to create _, err := roleBindingStorage.CreateRoleBindingWithEscalation(ctx, t) // Unconditional replace if it already exists if kapierrors.IsAlreadyExists(err) { _, _, err = roleBindingStorage.UpdateRoleBindingWithEscalation(ctx, t) } // Delete and recreate as a last resort if err != nil { roleBindingStorage.Delete(ctx, t.Name, nil) _, err = roleBindingStorage.CreateRoleBindingWithEscalation(ctx, t) } // Gather any error if err != nil { errs = append(errs, 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) } } case *authorizationapi.ClusterRole: ctx := kapi.WithNamespace(kapi.NewContext(), t.Namespace) if change { // Attempt to create _, err := clusterRoleStorage.CreateClusterRoleWithEscalation(ctx, t) // Unconditional replace if it already exists if kapierrors.IsAlreadyExists(err) { _, _, err = clusterRoleStorage.UpdateClusterRoleWithEscalation(ctx, t) } // Delete and recreate as a last resort if err != nil { clusterRoleStorage.Delete(ctx, t.Name, nil) _, err = clusterRoleStorage.CreateClusterRoleWithEscalation(ctx, t) } // Gather any error if err != nil { errs = append(errs, 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 { // Attempt to create _, err := clusterRoleBindingStorage.CreateClusterRoleBindingWithEscalation(ctx, t) // Unconditional replace if it already exists if kapierrors.IsAlreadyExists(err) { _, _, err = clusterRoleBindingStorage.UpdateClusterRoleBindingWithEscalation(ctx, t) } // Delete and recreate as a last resort if err != nil { clusterRoleBindingStorage.Delete(ctx, t.Name, nil) _, err = clusterRoleBindingStorage.CreateClusterRoleBindingWithEscalation(ctx, t) } // Gather any error if err != nil { errs = append(errs, 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) } } default: errs = append(errs, fmt.Errorf("only roles and rolebindings may be created in this mode, not: %v", reflect.TypeOf(t))) } } if !change { fmt.Fprintf(out, "To make the changes described above, pass --force\n") } return kerrors.NewAggregate(errs) }) }
// BuildMasterConfig builds and returns the OpenShift master configuration based on the // provided options func BuildMasterConfig(options configapi.MasterConfig) (*MasterConfig, error) { client, err := etcd.MakeEtcdClient(options.EtcdClientInfo) if err != nil { return nil, err } restOptsGetter := originrest.StorageOptions(options) clientCAs, err := configapi.GetClientCertCAPool(options) if err != nil { return nil, err } apiClientCAs, err := configapi.GetAPIClientCertCAPool(options) if err != nil { return nil, err } privilegedLoopbackKubeClient, _, err := configapi.GetKubeClient(options.MasterClients.OpenShiftLoopbackKubeConfig, options.MasterClients.OpenShiftLoopbackClientConnectionOverrides) if err != nil { return nil, err } privilegedLoopbackOpenShiftClient, privilegedLoopbackClientConfig, err := configapi.GetOpenShiftClient(options.MasterClients.OpenShiftLoopbackKubeConfig, options.MasterClients.OpenShiftLoopbackClientConnectionOverrides) if err != nil { return nil, err } customListerWatchers := shared.DefaultListerWatcherOverrides{} if err := addAuthorizationListerWatchers(customListerWatchers, restOptsGetter); err != nil { return nil, err } informerFactory := shared.NewInformerFactory(privilegedLoopbackKubeClient, privilegedLoopbackOpenShiftClient, customListerWatchers, 10*time.Minute) imageTemplate := variable.NewDefaultImageTemplate() imageTemplate.Format = options.ImageConfig.Format imageTemplate.Latest = options.ImageConfig.Latest defaultRegistry := env("OPENSHIFT_DEFAULT_REGISTRY", "${DOCKER_REGISTRY_SERVICE_HOST}:${DOCKER_REGISTRY_SERVICE_PORT}") svcCache := service.NewServiceResolverCache(privilegedLoopbackKubeClient.Services(kapi.NamespaceDefault).Get) defaultRegistryFunc, err := svcCache.Defer(defaultRegistry) if err != nil { return nil, fmt.Errorf("OPENSHIFT_DEFAULT_REGISTRY variable is invalid %q: %v", defaultRegistry, err) } requestContextMapper := kapi.NewRequestContextMapper() groupStorage, err := groupstorage.NewREST(restOptsGetter) if err != nil { return nil, err } groupCache := usercache.NewGroupCache(groupregistry.NewRegistry(groupStorage)) projectCache := projectcache.NewProjectCache(privilegedLoopbackKubeClient.Namespaces(), options.ProjectConfig.DefaultNodeSelector) clusterQuotaMappingController := clusterquotamapping.NewClusterQuotaMappingController(informerFactory.Namespaces(), informerFactory.ClusterResourceQuotas()) kubeletClientConfig := configapi.GetKubeletClientConfig(options) kubeClientSet := clientadapter.FromUnversionedClient(privilegedLoopbackKubeClient) quotaRegistry := quota.NewAllResourceQuotaRegistry(privilegedLoopbackOpenShiftClient, kubeClientSet) ruleResolver := rulevalidation.NewDefaultRuleResolver( informerFactory.Policies().Lister(), informerFactory.PolicyBindings().Lister(), informerFactory.ClusterPolicies().Lister().ClusterPolicies(), informerFactory.ClusterPolicyBindings().Lister().ClusterPolicyBindings(), ) authorizer := newAuthorizer(ruleResolver, informerFactory, options.ProjectConfig.ProjectRequestMessage) pluginInitializer := oadmission.PluginInitializer{ OpenshiftClient: privilegedLoopbackOpenShiftClient, ProjectCache: projectCache, OriginQuotaRegistry: quotaRegistry, Authorizer: authorizer, JenkinsPipelineConfig: options.JenkinsPipelineConfig, RESTClientConfig: *privilegedLoopbackClientConfig, Informers: informerFactory, ClusterQuotaMapper: clusterQuotaMappingController.GetClusterQuotaMapper(), DefaultRegistryFn: imageapi.DefaultRegistryFunc(defaultRegistryFunc), } originAdmission, kubeAdmission, err := buildAdmissionChains(options, kubeClientSet, pluginInitializer) if err != nil { return nil, err } serviceAccountTokenGetter, err := newServiceAccountTokenGetter(options) if err != nil { return nil, err } authenticator, err := newAuthenticator(options, restOptsGetter, serviceAccountTokenGetter, apiClientCAs, groupCache) if err != nil { return nil, err } plug, plugStart := newControllerPlug(options, client) config := &MasterConfig{ Options: options, RESTOptionsGetter: restOptsGetter, RuleResolver: ruleResolver, Authenticator: authenticator, Authorizer: authorizer, AuthorizationAttributeBuilder: newAuthorizationAttributeBuilder(requestContextMapper), GroupCache: groupCache, ProjectAuthorizationCache: newProjectAuthorizationCache(authorizer, privilegedLoopbackKubeClient, informerFactory), ProjectCache: projectCache, ClusterQuotaMappingController: clusterQuotaMappingController, RequestContextMapper: requestContextMapper, AdmissionControl: originAdmission, KubeAdmissionControl: kubeAdmission, TLS: configapi.UseTLS(options.ServingInfo.ServingInfo), ControllerPlug: plug, ControllerPlugStart: plugStart, ImageFor: imageTemplate.ExpandOrDie, RegistryNameFn: imageapi.DefaultRegistryFunc(defaultRegistryFunc), // TODO: migration of versions of resources stored in annotations must be sorted out ExternalVersionCodec: kapi.Codecs.LegacyCodec(unversioned.GroupVersion{Group: "", Version: "v1"}), KubeletClientConfig: kubeletClientConfig, ClientCAs: clientCAs, APIClientCAs: apiClientCAs, PrivilegedLoopbackClientConfig: *privilegedLoopbackClientConfig, PrivilegedLoopbackOpenShiftClient: privilegedLoopbackOpenShiftClient, PrivilegedLoopbackKubernetesClient: privilegedLoopbackKubeClient, Informers: informerFactory, } // ensure that the limit range informer will be started informer := config.Informers.LimitRanges().Informer() config.LimitVerifier = imageadmission.NewLimitVerifier(imageadmission.LimitRangesForNamespaceFunc(func(ns string) ([]*kapi.LimitRange, error) { list, err := config.Informers.LimitRanges().Lister().LimitRanges(ns).List(labels.Everything()) if err != nil { return nil, err } // the verifier must return an error if len(list) == 0 && len(informer.LastSyncResourceVersion()) == 0 { glog.V(4).Infof("LimitVerifier still waiting for ranges to load: %#v", informer) forbiddenErr := kapierrors.NewForbidden(unversioned.GroupResource{Resource: "limitranges"}, "", fmt.Errorf("the server is still loading limit information")) forbiddenErr.ErrStatus.Details.RetryAfterSeconds = 1 return nil, forbiddenErr } return list, nil })) return config, nil }
func makeLocalTestStorage() roleregistry.Storage { policyRegistry := test.NewPolicyRegistry(testNewLocalPolicies(), nil) return NewVirtualStorage(policyRegistry, rulevalidation.NewDefaultRuleResolver(policyRegistry, &test.PolicyBindingRegistry{}, &test.ClusterPolicyRegistry{}, &test.ClusterPolicyBindingRegistry{}), nil, authorizationapi.Resource("role")) }
func OverwriteBootstrapPolicy(optsGetter restoptions.Getter, policyFile, createBootstrapPolicyCommand string, change bool, out io.Writer) error { if !change { fmt.Fprintf(out, "Performing a dry run of policy overwrite:\n\n") } mapper := cmdclientcmd.ShortcutExpander{RESTMapper: kubectl.ShortcutExpander{RESTMapper: registered.RESTMapper()}} typer := kapi.Scheme clientMapper := resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) { return nil, nil }) r := resource.NewBuilder(mapper, typer, clientMapper, kapi.Codecs.UniversalDecoder()). FilenameParam(false, false, policyFile). Flatten(). Do() if r.Err() != nil { return r.Err() } policyStorage, err := policyetcd.NewStorage(optsGetter) if err != nil { return err } policyRegistry := policyregistry.NewRegistry(policyStorage) policyBindingStorage, err := policybindingetcd.NewStorage(optsGetter) if err != nil { return err } policyBindingRegistry := policybindingregistry.NewRegistry(policyBindingStorage) clusterPolicyStorage, err := clusterpolicyetcd.NewStorage(optsGetter) if err != nil { return err } clusterPolicyRegistry := clusterpolicyregistry.NewRegistry(clusterPolicyStorage) clusterPolicyBindingStorage, err := clusterpolicybindingetcd.NewStorage(optsGetter) if err != nil { return err } clusterPolicyBindingRegistry := clusterpolicybindingregistry.NewRegistry(clusterPolicyBindingStorage) ruleResolver := rulevalidation.NewDefaultRuleResolver( policyListerNamespacer{registry: policyRegistry}, policyBindingListerNamespacer{registry: policyBindingRegistry}, clusterpolicyregistry.ReadOnlyClusterPolicy{Registry: clusterPolicyRegistry}, clusterpolicybindingregistry.ReadOnlyClusterPolicyBinding{Registry: clusterPolicyBindingRegistry}, ) roleStorage := rolestorage.NewVirtualStorage(policyRegistry, ruleResolver) roleBindingStorage := rolebindingstorage.NewVirtualStorage(policyBindingRegistry, ruleResolver) clusterRoleStorage := clusterrolestorage.NewClusterRoleStorage(clusterPolicyRegistry, clusterPolicyBindingRegistry) clusterRoleBindingStorage := clusterrolebindingstorage.NewClusterRoleBindingStorage(clusterPolicyRegistry, clusterPolicyBindingRegistry) return r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } template, ok := info.Object.(*templateapi.Template) if !ok { return errors.New("policy must be contained in a template. One can be created with '" + createBootstrapPolicyCommand + "'.") } runtime.DecodeList(template.Objects, kapi.Codecs.UniversalDecoder()) for _, item := range template.Objects { switch t := item.(type) { case *authorizationapi.Role: ctx := kapi.WithNamespace(kapi.NewContext(), t.Namespace) if change { roleStorage.Delete(ctx, t.Name, nil) if _, err := roleStorage.CreateRoleWithEscalation(ctx, t); err != nil { 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) } } case *authorizationapi.RoleBinding: ctx := kapi.WithNamespace(kapi.NewContext(), t.Namespace) if change { roleBindingStorage.Delete(ctx, t.Name, nil) if _, err := roleBindingStorage.CreateRoleBindingWithEscalation(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(t, nil, nil); err == nil { fmt.Fprintf(out, "%s\n", s) } } case *authorizationapi.ClusterRole: ctx := kapi.WithNamespace(kapi.NewContext(), t.Namespace) if change { clusterRoleStorage.Delete(ctx, t.Name, nil) if _, err := clusterRoleStorage.CreateClusterRoleWithEscalation(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) } } default: return fmt.Errorf("only roles and rolebindings may be created in this mode, not: %v", reflect.TypeOf(t)) } } if !change { fmt.Fprintf(out, "To make the changes described above, pass --force\n") } return nil }) }
func (c *MasterConfig) GetRestStorage() map[string]rest.Storage { defaultRegistry := env("OPENSHIFT_DEFAULT_REGISTRY", "${DOCKER_REGISTRY_SERVICE_HOST}:${DOCKER_REGISTRY_SERVICE_PORT}") svcCache := service.NewServiceResolverCache(c.KubeClient().Services(kapi.NamespaceDefault).Get) defaultRegistryFunc, err := svcCache.Defer(defaultRegistry) if err != nil { glog.Fatalf("OPENSHIFT_DEFAULT_REGISTRY variable is invalid %q: %v", defaultRegistry, err) } kubeletClient, err := kubeletclient.NewStaticKubeletClient(c.KubeletClientConfig) if err != nil { glog.Fatalf("Unable to configure Kubelet client: %v", err) } // TODO: allow the system CAs and the local CAs to be joined together. importTransport, err := restclient.TransportFor(&restclient.Config{}) if err != nil { glog.Fatalf("Unable to configure a default transport for importing: %v", err) } insecureImportTransport, err := restclient.TransportFor(&restclient.Config{Insecure: true}) if err != nil { glog.Fatalf("Unable to configure a default transport for importing: %v", err) } applicationStorage := application.NewREST(c.EtcdHelper, c.PrivilegedLoopbackOpenShiftClient, c.PrivilegedLoopbackKubernetesClient) serviceBrokerStorage := servicebroker.NewREST(c.EtcdHelper, c.BackingServiceInstanceControllerClients()) backingServiceStorage := backingservice.NewREST(c.EtcdHelper, c.BackingServiceInstanceControllerClients()) buildStorage, buildDetailsStorage := buildetcd.NewREST(c.EtcdHelper) buildRegistry := buildregistry.NewRegistry(buildStorage) buildConfigStorage := buildconfigetcd.NewREST(c.EtcdHelper) buildConfigRegistry := buildconfigregistry.NewRegistry(buildConfigStorage) deployConfigStorage, deployConfigScaleStorage := deployconfigetcd.NewREST(c.EtcdHelper, c.DeploymentConfigScaleClient()) deployConfigRegistry := deployconfigregistry.NewRegistry(deployConfigStorage) routeAllocator := c.RouteAllocator() routeStorage, routeStatusStorage := routeetcd.NewREST(c.EtcdHelper, routeAllocator) hostSubnetStorage := hostsubnetetcd.NewREST(c.EtcdHelper) netNamespaceStorage := netnamespaceetcd.NewREST(c.EtcdHelper) clusterNetworkStorage := clusternetworketcd.NewREST(c.EtcdHelper) userStorage := useretcd.NewREST(c.EtcdHelper) userRegistry := userregistry.NewRegistry(userStorage) identityStorage := identityetcd.NewREST(c.EtcdHelper) identityRegistry := identityregistry.NewRegistry(identityStorage) userIdentityMappingStorage := useridentitymapping.NewREST(userRegistry, identityRegistry) policyStorage := policyetcd.NewStorage(c.EtcdHelper) policyRegistry := policyregistry.NewRegistry(policyStorage) policyBindingStorage := policybindingetcd.NewStorage(c.EtcdHelper) policyBindingRegistry := policybindingregistry.NewRegistry(policyBindingStorage) clusterPolicyStorage := clusterpolicystorage.NewStorage(c.EtcdHelper) clusterPolicyRegistry := clusterpolicyregistry.NewRegistry(clusterPolicyStorage) clusterPolicyBindingStorage := clusterpolicybindingstorage.NewStorage(c.EtcdHelper) clusterPolicyBindingRegistry := clusterpolicybindingregistry.NewRegistry(clusterPolicyBindingStorage) ruleResolver := rulevalidation.NewDefaultRuleResolver( policyRegistry, policyBindingRegistry, clusterPolicyRegistry, clusterPolicyBindingRegistry, ) roleStorage := rolestorage.NewVirtualStorage(policyRegistry, ruleResolver) roleBindingStorage := rolebindingstorage.NewVirtualStorage(policyBindingRegistry, ruleResolver) clusterRoleStorage := clusterrolestorage.NewClusterRoleStorage(clusterPolicyRegistry, clusterPolicyBindingRegistry) clusterRoleBindingStorage := clusterrolebindingstorage.NewClusterRoleBindingStorage(clusterPolicyRegistry, clusterPolicyBindingRegistry) subjectAccessReviewStorage := subjectaccessreview.NewREST(c.Authorizer) subjectAccessReviewRegistry := subjectaccessreview.NewRegistry(subjectAccessReviewStorage) localSubjectAccessReviewStorage := localsubjectaccessreview.NewREST(subjectAccessReviewRegistry) resourceAccessReviewStorage := resourceaccessreview.NewREST(c.Authorizer) resourceAccessReviewRegistry := resourceaccessreview.NewRegistry(resourceAccessReviewStorage) localResourceAccessReviewStorage := localresourceaccessreview.NewREST(resourceAccessReviewRegistry) imageStorage := imageetcd.NewREST(c.EtcdHelper) imageRegistry := image.NewRegistry(imageStorage) imageStreamSecretsStorage := imagesecret.NewREST(c.ImageStreamSecretClient()) imageStreamStorage, imageStreamStatusStorage, internalImageStreamStorage := imagestreametcd.NewREST(c.EtcdHelper, imagestream.DefaultRegistryFunc(defaultRegistryFunc), subjectAccessReviewRegistry) imageStreamRegistry := imagestream.NewRegistry(imageStreamStorage, imageStreamStatusStorage, internalImageStreamStorage) imageStreamMappingStorage := imagestreammapping.NewREST(imageRegistry, imageStreamRegistry) imageStreamTagStorage := imagestreamtag.NewREST(imageRegistry, imageStreamRegistry) imageStreamTagRegistry := imagestreamtag.NewRegistry(imageStreamTagStorage) importerFn := func(r importer.RepositoryRetriever) imageimporter.Interface { return imageimporter.NewImageStreamImporter(r, c.Options.ImagePolicyConfig.MaxImagesBulkImportedPerRepository, util.NewTokenBucketRateLimiter(2.0, 3)) } importerDockerClientFn := func() dockerregistry.Client { return dockerregistry.NewClient(20*time.Second, false) } imageStreamImportStorage := imagestreamimport.NewREST(importerFn, imageStreamRegistry, internalImageStreamStorage, imageStorage, c.ImageStreamImportSecretClient(), importTransport, insecureImportTransport, importerDockerClientFn) imageStreamImageStorage := imagestreamimage.NewREST(imageRegistry, imageStreamRegistry) imageStreamImageRegistry := imagestreamimage.NewRegistry(imageStreamImageStorage) backingServiceInstanceEtcd := backingserviceinstanceetcd.NewREST(c.EtcdHelper) backingServiceInstanceRegistry := backingserviceinstanceregistry.NewRegistry(backingServiceInstanceEtcd) backingServiceInstanceBindingEtcd := backingserviceinstanceetcd.NewBindingREST(backingServiceInstanceRegistry, deployConfigRegistry) buildGenerator := &buildgenerator.BuildGenerator{ Client: buildgenerator.Client{ GetBuildConfigFunc: buildConfigRegistry.GetBuildConfig, UpdateBuildConfigFunc: buildConfigRegistry.UpdateBuildConfig, GetBuildFunc: buildRegistry.GetBuild, CreateBuildFunc: buildRegistry.CreateBuild, GetImageStreamFunc: imageStreamRegistry.GetImageStream, GetImageStreamImageFunc: imageStreamImageRegistry.GetImageStreamImage, GetImageStreamTagFunc: imageStreamTagRegistry.GetImageStreamTag, }, ServiceAccounts: c.KubeClient(), Secrets: c.KubeClient(), } // TODO: with sharding, this needs to be changed deployConfigGenerator := &deployconfiggenerator.DeploymentConfigGenerator{ Client: deployconfiggenerator.Client{ DCFn: deployConfigRegistry.GetDeploymentConfig, ISFn: imageStreamRegistry.GetImageStream, LISFn2: imageStreamRegistry.ListImageStreams, }, } configClient, kclient := c.DeploymentConfigClients() deployRollback := &deployrollback.RollbackGenerator{} deployRollbackClient := deployrollback.Client{ DCFn: deployConfigRegistry.GetDeploymentConfig, RCFn: clientDeploymentInterface{kclient}.GetDeployment, GRFn: deployRollback.GenerateRollback, } projectStorage := projectproxy.NewREST(kclient.Namespaces(), c.ProjectAuthorizationCache) namespace, templateName, err := configapi.ParseNamespaceAndName(c.Options.ProjectConfig.ProjectRequestTemplate) if err != nil { glog.Errorf("Error parsing project request template value: %v", err) // we can continue on, the storage that gets created will be valid, it simply won't work properly. There's no reason to kill the master } projectRequestStorage := projectrequeststorage.NewREST(c.Options.ProjectConfig.ProjectRequestMessage, namespace, templateName, c.PrivilegedLoopbackOpenShiftClient, c.PrivilegedLoopbackKubernetesClient) bcClient := c.BuildConfigWebHookClient() buildConfigWebHooks := buildconfigregistry.NewWebHookREST( buildConfigRegistry, buildclient.NewOSClientBuildConfigInstantiatorClient(bcClient), map[string]webhook.Plugin{ "generic": generic.New(), "github": github.New(), }, ) storage := map[string]rest.Storage{ "images": imageStorage, "imageStreams/secrets": imageStreamSecretsStorage, "imageStreams": imageStreamStorage, "imageStreams/status": imageStreamStatusStorage, "imageStreamImports": imageStreamImportStorage, "imageStreamImages": imageStreamImageStorage, "imageStreamMappings": imageStreamMappingStorage, "imageStreamTags": imageStreamTagStorage, "applications": applicationStorage, "serviceBrokers": serviceBrokerStorage, "backingServices": backingServiceStorage, "backingServiceInstances": backingServiceInstanceEtcd, "backingServiceInstances/binding": backingServiceInstanceBindingEtcd, "deploymentConfigs": deployConfigStorage, "deploymentConfigs/scale": deployConfigScaleStorage, "generateDeploymentConfigs": deployconfiggenerator.NewREST(deployConfigGenerator, c.EtcdHelper.Codec()), "deploymentConfigRollbacks": deployrollback.NewREST(deployRollbackClient, c.EtcdHelper.Codec()), "deploymentConfigs/log": deploylogregistry.NewREST(configClient, kclient, c.DeploymentLogClient(), kubeletClient), "processedTemplates": templateregistry.NewREST(), "templates": templateetcd.NewREST(c.EtcdHelper), "routes": routeStorage, "routes/status": routeStatusStorage, "projects": projectStorage, "projectRequests": projectRequestStorage, "hostSubnets": hostSubnetStorage, "netNamespaces": netNamespaceStorage, "clusterNetworks": clusterNetworkStorage, "users": userStorage, "groups": groupetcd.NewREST(c.EtcdHelper), "identities": identityStorage, "userIdentityMappings": userIdentityMappingStorage, "oAuthAuthorizeTokens": authorizetokenetcd.NewREST(c.EtcdHelper), "oAuthAccessTokens": accesstokenetcd.NewREST(c.EtcdHelper), "oAuthClients": clientetcd.NewREST(c.EtcdHelper), "oAuthClientAuthorizations": clientauthetcd.NewREST(c.EtcdHelper), "resourceAccessReviews": resourceAccessReviewStorage, "subjectAccessReviews": subjectAccessReviewStorage, "localSubjectAccessReviews": localSubjectAccessReviewStorage, "localResourceAccessReviews": localResourceAccessReviewStorage, "policies": policyStorage, "policyBindings": policyBindingStorage, "roles": roleStorage, "roleBindings": roleBindingStorage, "clusterPolicies": clusterPolicyStorage, "clusterPolicyBindings": clusterPolicyBindingStorage, "clusterRoleBindings": clusterRoleBindingStorage, "clusterRoles": clusterRoleStorage, } if configapi.IsBuildEnabled(&c.Options) { storage["builds"] = buildStorage storage["buildConfigs"] = buildConfigStorage storage["buildConfigs/webhooks"] = buildConfigWebHooks storage["builds/clone"] = buildclone.NewStorage(buildGenerator) storage["buildConfigs/instantiate"] = buildconfiginstantiate.NewStorage(buildGenerator) storage["buildConfigs/instantiatebinary"] = buildconfiginstantiate.NewBinaryStorage(buildGenerator, buildStorage, c.BuildLogClient(), kubeletClient) storage["builds/log"] = buildlogregistry.NewREST(buildStorage, buildStorage, c.BuildLogClient(), kubeletClient) storage["builds/details"] = buildDetailsStorage } return storage }
// BuildMasterConfig builds and returns the OpenShift master configuration based on the // provided options func BuildMasterConfig(options configapi.MasterConfig) (*MasterConfig, error) { client, err := etcd.EtcdClient(options.EtcdClientInfo) if err != nil { return nil, err } etcdClient, err := etcd.MakeNewEtcdClient(options.EtcdClientInfo) if err != nil { return nil, err } groupVersion := unversioned.GroupVersion{Group: "", Version: options.EtcdStorageConfig.OpenShiftStorageVersion} etcdHelper, err := NewEtcdStorage(etcdClient, groupVersion, options.EtcdStorageConfig.OpenShiftStoragePrefix) if err != nil { return nil, fmt.Errorf("Error setting up server storage: %v", err) } clientCAs, err := configapi.GetClientCertCAPool(options) if err != nil { return nil, err } apiClientCAs, err := configapi.GetAPIClientCertCAPool(options) if err != nil { return nil, err } privilegedLoopbackKubeClient, _, err := configapi.GetKubeClient(options.MasterClients.OpenShiftLoopbackKubeConfig) if err != nil { return nil, err } privilegedLoopbackOpenShiftClient, privilegedLoopbackClientConfig, err := configapi.GetOpenShiftClient(options.MasterClients.OpenShiftLoopbackKubeConfig) if err != nil { return nil, err } imageTemplate := variable.NewDefaultImageTemplate() imageTemplate.Format = options.ImageConfig.Format imageTemplate.Latest = options.ImageConfig.Latest policyCache, policyClient := newReadOnlyCacheAndClient(etcdHelper) requestContextMapper := kapi.NewRequestContextMapper() groupCache := usercache.NewGroupCache(groupregistry.NewRegistry(groupstorage.NewREST(etcdHelper))) projectCache := projectcache.NewProjectCache(privilegedLoopbackKubeClient.Namespaces(), options.ProjectConfig.DefaultNodeSelector) kubeletClientConfig := configapi.GetKubeletClientConfig(options) // in-order list of plug-ins that should intercept admission decisions (origin only intercepts) admissionControlPluginNames := []string{"ProjectRequestLimit", "OriginNamespaceLifecycle", "PodNodeConstraints", "BuildByStrategy", "OriginResourceQuota"} if len(options.AdmissionConfig.PluginOrderOverride) > 0 { admissionControlPluginNames = options.AdmissionConfig.PluginOrderOverride } ruleResolver := rulevalidation.NewDefaultRuleResolver( rulevalidation.PolicyGetter(policyClient), rulevalidation.BindingLister(policyClient), rulevalidation.ClusterPolicyGetter(policyClient), rulevalidation.ClusterBindingLister(policyClient), ) authorizer := newAuthorizer(ruleResolver, policyClient, options.ProjectConfig.ProjectRequestMessage) pluginInitializer := oadmission.PluginInitializer{ OpenshiftClient: privilegedLoopbackOpenShiftClient, ProjectCache: projectCache, Authorizer: authorizer, } plugins := []admission.Interface{} clientsetClient := clientadapter.FromUnversionedClient(privilegedLoopbackKubeClient) for _, pluginName := range admissionControlPluginNames { configFile, err := pluginconfig.GetPluginConfig(options.AdmissionConfig.PluginConfig[pluginName]) if err != nil { return nil, err } plugin := admission.InitPlugin(pluginName, clientsetClient, configFile) if plugin != nil { plugins = append(plugins, plugin) } } pluginInitializer.Initialize(plugins) // ensure that plugins have been properly initialized if err := oadmission.Validate(plugins); err != nil { return nil, err } admissionController := admission.NewChainHandler(plugins...) serviceAccountTokenGetter, err := newServiceAccountTokenGetter(options, etcdClient) if err != nil { return nil, err } plug, plugStart := newControllerPlug(options, client) config := &MasterConfig{ Options: options, RuleResolver: ruleResolver, Authenticator: newAuthenticator(options, etcdHelper, serviceAccountTokenGetter, apiClientCAs, groupCache), Authorizer: authorizer, AuthorizationAttributeBuilder: newAuthorizationAttributeBuilder(requestContextMapper), PolicyCache: policyCache, GroupCache: groupCache, ProjectAuthorizationCache: newProjectAuthorizationCache(authorizer, privilegedLoopbackKubeClient, policyClient), ProjectCache: projectCache, RequestContextMapper: requestContextMapper, AdmissionControl: admissionController, TLS: configapi.UseTLS(options.ServingInfo.ServingInfo), ControllerPlug: plug, ControllerPlugStart: plugStart, ImageFor: imageTemplate.ExpandOrDie, EtcdHelper: etcdHelper, KubeletClientConfig: kubeletClientConfig, ClientCAs: clientCAs, APIClientCAs: apiClientCAs, PluginInitializer: pluginInitializer, PrivilegedLoopbackClientConfig: *privilegedLoopbackClientConfig, PrivilegedLoopbackOpenShiftClient: privilegedLoopbackOpenShiftClient, PrivilegedLoopbackKubernetesClient: privilegedLoopbackKubeClient, } return config, nil }