diff --git a/pkg/webhook/pod/containerregistry.go b/pkg/webhook/pod/containerregistry.go index af047643..b7de5235 100644 --- a/pkg/webhook/pod/containerregistry.go +++ b/pkg/webhook/pod/containerregistry.go @@ -48,14 +48,22 @@ func (h *containerRegistryHandler) OnCreate(c client.Client, decoder *admission. var valid, matched bool for _, container := range pod.Spec.Containers { - registry := NewRegistry(container.Image) + reg := NewRegistry(container.Image) - valid = tnt.Spec.ContainerRegistries.ExactMatch(registry.Registry()) + if len(reg.Registry()) == 0 { + recorder.Eventf(&tnt, corev1.EventTypeWarning, "MissingFQCI", "Pod %s/%s is not using using a fully qualified container image, cannot enforce registry the current Tenant", req.Namespace, req.Name, reg.Registry()) - matched = tnt.Spec.ContainerRegistries.RegexMatch(registry.Registry()) + response := admission.Denied(NewContainerRegistryForbidden(container.Image, *tnt.Spec.ContainerRegistries).Error()) + + return &response + } + + valid = tnt.Spec.ContainerRegistries.ExactMatch(reg.Registry()) + + matched = tnt.Spec.ContainerRegistries.RegexMatch(reg.Registry()) if !valid && !matched { - recorder.Eventf(&tnt, corev1.EventTypeWarning, "ForbiddenContainerRegistry", "Pod %s/%s is using a forbidden registry %s is forbidden for the current Tenant", req.Namespace, req.Name, registry.Registry()) + recorder.Eventf(&tnt, corev1.EventTypeWarning, "ForbiddenContainerRegistry", "Pod %s/%s is using a container hosted on registry %s that is forbidden for the current Tenant", req.Namespace, req.Name, reg.Registry()) response := admission.Denied(NewContainerRegistryForbidden(container.Image, *tnt.Spec.ContainerRegistries).Error()) diff --git a/pkg/webhook/pod/containerregistry_errors.go b/pkg/webhook/pod/containerregistry_errors.go index a20fda51..d7e5f373 100644 --- a/pkg/webhook/pod/containerregistry_errors.go +++ b/pkg/webhook/pod/containerregistry_errors.go @@ -11,20 +11,32 @@ import ( capsulev1beta1 "github.com/clastix/capsule/api/v1beta1" ) +type missingContainerRegistryError struct { + fqci string +} + +func (m missingContainerRegistryError) Error() string { + return fmt.Sprintf("container image %s is missing repository, please, use a fully qualified container image name", m.fqci) +} + +func NewMissingContainerRegistryError(image string) error { + return &missingContainerRegistryError{fqci: image} +} + type registryClassForbidden struct { - fqdi string + fqci string spec capsulev1beta1.AllowedListSpec } func NewContainerRegistryForbidden(image string, spec capsulev1beta1.AllowedListSpec) error { return ®istryClassForbidden{ - fqdi: image, + fqci: image, spec: spec, } } func (f registryClassForbidden) Error() (err string) { - err = fmt.Sprintf("Container image %s registry is forbidden for the current Tenant: ", f.fqdi) + err = fmt.Sprintf("Container image %s registry is forbidden for the current Tenant: ", f.fqci) var extra []string if len(f.spec.Exact) > 0 { extra = append(extra, fmt.Sprintf("use one from the following list (%s)", strings.Join(f.spec.Exact, ", "))) diff --git a/pkg/webhook/pod/containerregistry_registry.go b/pkg/webhook/pod/containerregistry_registry.go index 1ab58f75..68d6ea84 100644 --- a/pkg/webhook/pod/containerregistry_registry.go +++ b/pkg/webhook/pod/containerregistry_registry.go @@ -7,8 +7,6 @@ import ( "regexp" ) -const defaultRegistryName = "docker.io" - type registry map[string]string func (r registry) Registry() string { @@ -16,9 +14,7 @@ func (r registry) Registry() string { if !ok { return "" } - if len(res) == 0 { - return defaultRegistryName - } + return res } @@ -27,9 +23,7 @@ func (r registry) Repository() string { if !ok { return "" } - if res == defaultRegistryName { - return "" - } + return res } @@ -38,6 +32,7 @@ func (r registry) Image() string { if !ok { return "" } + return res } @@ -54,7 +49,7 @@ func (r registry) Tag() string { func NewRegistry(value string) Registry { reg := make(registry) - r := regexp.MustCompile(`(((?P[a-zA-Z0-9-._]+)\/)?((?P[a-zA-Z0-9-._]+)\/))?(?P[a-zA-Z0-9-._]+)(:(?P[a-zA-Z0-9-._]+))?`) + r := regexp.MustCompile(`((?P[a-zA-Z0-9-._]+(:\d+)?)\/)?(?P.*\/)?(?P[a-zA-Z0-9-._]+:(?P[a-zA-Z0-9-._]+))?`) match := r.FindStringSubmatch(value) for i, name := range r.SubexpNames() { if i > 0 && i <= len(match) {