Skip to content

Commit

Permalink
Add GitRepoRestriction
Browse files Browse the repository at this point in the history
  • Loading branch information
ibuildthecloud committed Aug 31, 2020
1 parent 94c77ce commit fc0bc37
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 6 deletions.
15 changes: 15 additions & 0 deletions pkg/apis/fleet.cattle.io/v1alpha1/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,18 @@ type GitRepoDisplay struct {
ReadyBundleDeployments string `json:"readyBundleDeployments,omitempty"`
State string `json:"state,omitempty"`
}

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type GitRepoRestriction struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

DefaultServiceAccount string `json:"defaultServiceAccount,omitempty"`
AllowedServiceAccounts []string `json:"allowedServiceAccounts,omitempty"`
AllowedRepoPatterns []string `json:"allowedRepoPatterns,omitempty"`

DefaultClientSecretName string `json:"defaultClientSecretName,omitempty"`
AllowedClientSecretNames []string `json:"allowedClientSecretNames,omitempty"`
}
1 change: 1 addition & 0 deletions pkg/controllers/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ func Register(ctx context.Context, systemNamespace string, cfg clientcmd.ClientC
appCtx.Core.ServiceAccount()),
appCtx.GitJob.GitJob(),
appCtx.BundleDeployment(),
appCtx.GitRepoRestriction().Cache(),
appCtx.GitRepo())

bootstrap.Register(ctx,
Expand Down
105 changes: 99 additions & 6 deletions pkg/controllers/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package git
import (
"context"
"encoding/json"
"fmt"
"regexp"
"sort"
"time"

Expand Down Expand Up @@ -32,13 +34,15 @@ func Register(ctx context.Context,
apply apply.Apply,
gitJobs v1.GitJobController,
bundleDeployments fleetcontrollers.BundleDeploymentController,
gitRepoRestrictions fleetcontrollers.GitRepoRestrictionCache,
gitRepos fleetcontrollers.GitRepoController) {
h := &handler{
gitjobCache: gitJobs.Cache(),
bundleDeployments: bundleDeployments.Cache(),
gitjobCache: gitJobs.Cache(),
bundleDeployments: bundleDeployments.Cache(),
gitRepoRestrictions: gitRepoRestrictions,
}

fleetcontrollers.RegisterGitRepoGeneratingHandler(ctx, gitRepos, apply, "", "gitjobs", h.OnChange, nil)
fleetcontrollers.RegisterGitRepoGeneratingHandler(ctx, gitRepos, apply, "Accepted", "gitjobs", h.OnChange, nil)
relatedresource.Watch(ctx, "gitjobs",
relatedresource.OwnerResolver(true, fleet.SchemeGroupVersion.String(), "GitRepo"), gitRepos, gitJobs)
relatedresource.Watch(ctx, "gitjobs", resolveGitRepo, gitRepos, bundleDeployments)
Expand All @@ -59,8 +63,9 @@ func resolveGitRepo(namespace, name string, obj runtime.Object) ([]relatedresour
}

type handler struct {
gitjobCache v1.GitJobCache
bundleDeployments fleetcontrollers.BundleDeploymentCache
gitjobCache v1.GitJobCache
gitRepoRestrictions fleetcontrollers.GitRepoRestrictionCache
bundleDeployments fleetcontrollers.BundleDeploymentCache
}

func targetsOrDefault(targets []fleet.GitTarget) []fleet.GitTarget {
Expand Down Expand Up @@ -107,11 +112,99 @@ func (h *handler) getConfig(repo *fleet.GitRepo) (*corev1.ConfigMap, error) {
}, nil
}

func (h *handler) authorizeAndAssignDefaults(gitrepo *fleet.GitRepo) (*fleet.GitRepo, error) {
restrictions, err := h.gitRepoRestrictions.List(gitrepo.Namespace, labels.Everything())
if err != nil {
return nil, err
}

if len(restrictions) == 0 {
return gitrepo, nil
}

restriction := aggregate(restrictions)
gitrepo = gitrepo.DeepCopy()

gitrepo.Spec.ServiceAccount, err = isAllowed(gitrepo.Spec.ServiceAccount,
restriction.DefaultServiceAccount,
restriction.AllowedServiceAccounts,
false)
if err != nil {
return nil, fmt.Errorf("disallowed serviceAcount %s: %w", gitrepo.Spec.ServiceAccount, err)
}

gitrepo.Spec.Repo, err = isAllowed(gitrepo.Spec.Repo,
"",
restriction.AllowedRepoPatterns,
true)
if err != nil {
return nil, fmt.Errorf("disallowed repo %s: %w", gitrepo.Spec.ServiceAccount, err)
}

gitrepo.Spec.ClientSecretName, err = isAllowed(gitrepo.Spec.ClientSecretName,
restriction.DefaultClientSecretName,
restriction.AllowedClientSecretNames, false)
if err != nil {
return nil, fmt.Errorf("disallowed clientSecretName %s: %w", gitrepo.Spec.ServiceAccount, err)
}

return gitrepo, nil
}

func isAllowed(currentValue, defaultValue string, allowedValues []string, pattern bool) (string, error) {
if currentValue == "" {
return defaultValue, nil
}
if len(allowedValues) == 0 {
return currentValue, nil
}
for _, allowedValue := range allowedValues {
if allowedValue == currentValue {
return currentValue, nil
}
if !pattern {
continue
}
p, err := regexp.Compile(allowedValue)
if err != nil {
return currentValue, err
}
if p.MatchString(allowedValue) {
return currentValue, nil
}
}

return currentValue, fmt.Errorf("%s not in allowed set %v", currentValue, allowedValues)
}

func aggregate(restrictions []*fleet.GitRepoRestriction) (result fleet.GitRepoRestriction) {
sort.Slice(restrictions, func(i, j int) bool {
return restrictions[i].Name < restrictions[j].Name
})
for _, restriction := range restrictions {
if result.DefaultServiceAccount == "" {
result.DefaultServiceAccount = restriction.DefaultServiceAccount
}
if result.DefaultClientSecretName == "" {
result.DefaultClientSecretName = restriction.DefaultClientSecretName
}
result.AllowedServiceAccounts = append(result.AllowedServiceAccounts, restriction.AllowedServiceAccounts...)
result.AllowedClientSecretNames = append(result.AllowedClientSecretNames, restriction.AllowedClientSecretNames...)
result.AllowedRepoPatterns = append(result.AllowedRepoPatterns, restriction.AllowedRepoPatterns...)
}
return
}

func (h *handler) OnChange(gitrepo *fleet.GitRepo, status fleet.GitRepoStatus) ([]runtime.Object, fleet.GitRepoStatus, error) {
gitrepo, err := h.authorizeAndAssignDefaults(gitrepo)
if err != nil {
return nil, status, err
}

status.Conditions = nil
status.ObservedGeneration = gitrepo.Generation

status, err := h.setBundleDeploymentStatus(gitrepo, status)
status, err = h.setBundleDeploymentStatus(gitrepo, status)
if err != nil {
return nil, status, err
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/crd/crds.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ func List() []crd.CRD {
WithColumn("Cluster-Name", ".status.clusterName").
WithColumn("Labels", ".spec.clusterLabels")
}),
newCRD(&fleet.GitRepoRestriction{}, func(c crd.CRD) crd.CRD {
return c.
WithColumn("Default-ServiceAccount", ".defaultServiceAccount").
WithColumn("Allowed-ServiceAccounts", ".allowedServiceAccounts")
}),
newCRD(&fleet.Content{}, func(c crd.CRD) crd.CRD {
c.NonNamespace = true
c.Status = false
Expand Down

0 comments on commit fc0bc37

Please sign in to comment.