From 23ed3ba4c4a60602ce3efd3f4abdaa31c639879b Mon Sep 17 00:00:00 2001 From: Manuel Alejandro de Brito Fontes Date: Thu, 15 Aug 2019 20:25:35 -0400 Subject: [PATCH] Fix file permissions to support volumes --- cmd/nginx/main.go | 6 + internal/file/filesystem.go | 2 +- internal/file/structure.go | 28 +++++ internal/ingress/controller/checker_test.go | 2 +- .../ingress/controller/controller_test.go | 6 + internal/net/ssl/ssl.go | 16 --- .../settings/pod_security_policy_volumes.go | 106 ++++++++++++++++++ 7 files changed, 148 insertions(+), 18 deletions(-) create mode 100644 test/e2e/settings/pod_security_policy_volumes.go diff --git a/cmd/nginx/main.go b/cmd/nginx/main.go index 50c4c7d24e..ab5e4ee9d2 100644 --- a/cmd/nginx/main.go +++ b/cmd/nginx/main.go @@ -39,6 +39,7 @@ import ( "k8s.io/client-go/tools/clientcmd" "k8s.io/klog" + "k8s.io/ingress-nginx/internal/file" "k8s.io/ingress-nginx/internal/ingress/controller" "k8s.io/ingress-nginx/internal/ingress/metric" "k8s.io/ingress-nginx/internal/k8s" @@ -62,6 +63,11 @@ func main() { klog.Fatal(err) } + err = file.CreateRequiredDirectories() + if err != nil { + klog.Fatal(err) + } + kubeClient, err := createApiserverClient(conf.APIServerHost, conf.KubeConfigFile) if err != nil { handleFatalInitError(err) diff --git a/internal/file/filesystem.go b/internal/file/filesystem.go index 3a754dd19c..7c0db9f12f 100644 --- a/internal/file/filesystem.go +++ b/internal/file/filesystem.go @@ -17,4 +17,4 @@ limitations under the License. package file // ReadWriteByUser defines linux permission to read and write files for the owner user -const ReadWriteByUser = 0660 +const ReadWriteByUser = 0700 diff --git a/internal/file/structure.go b/internal/file/structure.go index acb52ffd82..485db79c8e 100644 --- a/internal/file/structure.go +++ b/internal/file/structure.go @@ -16,6 +16,12 @@ limitations under the License. package file +import ( + "os" + + "github.com/pkg/errors" +) + const ( // AuthDirectory default directory used to store files // to authenticate request @@ -34,3 +40,25 @@ var ( AuthDirectory, } ) + +// CreateRequiredDirectories verifies if the required directories to +// start the ingress controller exist and creates the missing ones. +func CreateRequiredDirectories() error { + for _, directory := range directories { + _, err := os.Stat(directory) + if err != nil { + if os.IsNotExist(err) { + err = os.MkdirAll(directory, ReadWriteByUser) + if err != nil { + return errors.Wrapf(err, "creating directory '%v'", directory) + } + + continue + } + + return errors.Wrapf(err, "checking directory %v", directory) + } + } + + return nil +} diff --git a/internal/ingress/controller/checker_test.go b/internal/ingress/controller/checker_test.go index f653b30422..6e7f2f29e8 100644 --- a/internal/ingress/controller/checker_test.go +++ b/internal/ingress/controller/checker_test.go @@ -37,7 +37,7 @@ func TestNginxCheck(t *testing.T) { listener, err := net.Listen("unix", nginx.StatusSocket) if err != nil { - t.Errorf("crating unix listener: %s", err) + t.Fatalf("crating unix listener: %s", err) } defer listener.Close() defer os.Remove(nginx.StatusSocket) diff --git a/internal/ingress/controller/controller_test.go b/internal/ingress/controller/controller_test.go index 0fecf50856..60d9f3b2b0 100644 --- a/internal/ingress/controller/controller_test.go +++ b/internal/ingress/controller/controller_test.go @@ -37,6 +37,7 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes/fake" + "k8s.io/ingress-nginx/internal/file" "k8s.io/ingress-nginx/internal/ingress" "k8s.io/ingress-nginx/internal/ingress/annotations" "k8s.io/ingress-nginx/internal/ingress/annotations/canary" @@ -154,6 +155,11 @@ func TestCheckIngress(t *testing.T) { }) }() + err := file.CreateRequiredDirectories() + if err != nil { + t.Fatal(err) + } + // Ensure no panic with wrong arguments var nginx *NGINXController nginx.CheckIngress(nil) diff --git a/internal/net/ssl/ssl.go b/internal/net/ssl/ssl.go index 16239fbc1d..f9a31fb37a 100644 --- a/internal/net/ssl/ssl.go +++ b/internal/net/ssl/ssl.go @@ -53,22 +53,6 @@ const ( fakeCertificateName = "default-fake-certificate" ) -func init() { - _, err := os.Stat(file.DefaultSSLDirectory) - if err != nil { - if os.IsNotExist(err) { - err = os.MkdirAll(file.DefaultSSLDirectory, file.ReadWriteByUser) - if err != nil { - klog.Fatalf("Unexpected error checking for default SSL directory: %v", err) - } - - return - } - - klog.Fatalf("Unexpected error checking for default SSL directory: %v", err) - } -} - // getPemFileName returns absolute file path and file name of pem cert related to given fullSecretName func getPemFileName(fullSecretName string) (string, string) { pemName := fmt.Sprintf("%v.pem", fullSecretName) diff --git a/test/e2e/settings/pod_security_policy_volumes.go b/test/e2e/settings/pod_security_policy_volumes.go new file mode 100644 index 0000000000..5c6e297c51 --- /dev/null +++ b/test/e2e/settings/pod_security_policy_volumes.go @@ -0,0 +1,106 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package settings + +import ( + "fmt" + "net/http" + "strings" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/parnurzeal/gorequest" + + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + k8sErrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "k8s.io/ingress-nginx/test/e2e/framework" +) + +var _ = framework.IngressNginxDescribe("Pod Security Policies with volumes", func() { + f := framework.NewDefaultFramework("pod-security-policies-volumes") + + It("should be running with a Pod Security Policy", func() { + psp := createPodSecurityPolicy() + _, err := f.KubeClientSet.ExtensionsV1beta1().PodSecurityPolicies().Create(psp) + if !k8sErrors.IsAlreadyExists(err) { + Expect(err).NotTo(HaveOccurred(), "creating Pod Security Policy") + } + + role, err := f.KubeClientSet.RbacV1().ClusterRoles().Get(fmt.Sprintf("nginx-ingress-clusterrole-%v", f.Namespace), metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred(), "getting ingress controller cluster role") + Expect(role).NotTo(BeNil()) + + role.Rules = append(role.Rules, rbacv1.PolicyRule{ + APIGroups: []string{"policy"}, + Resources: []string{"podsecuritypolicies"}, + ResourceNames: []string{ingressControllerPSP}, + Verbs: []string{"use"}, + }) + + _, err = f.KubeClientSet.RbacV1().ClusterRoles().Update(role) + Expect(err).NotTo(HaveOccurred(), "updating ingress controller cluster role to use a pod security policy") + + err = framework.UpdateDeployment(f.KubeClientSet, f.Namespace, "nginx-ingress-controller", 1, + func(deployment *appsv1.Deployment) error { + args := deployment.Spec.Template.Spec.Containers[0].Args + args = append(args, "--v=2") + deployment.Spec.Template.Spec.Containers[0].Args = args + + deployment.Spec.Template.Spec.Volumes = []corev1.Volume{ + { + Name: "ssl", VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + } + + fsGroup := int64(33) + deployment.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{ + FSGroup: &fsGroup, + } + + deployment.Spec.Template.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{ + { + Name: "ssl", MountPath: "/etc/ingress-controller", + }, + } + + _, err := f.KubeClientSet.AppsV1().Deployments(f.Namespace).Update(deployment) + + return err + }) + Expect(err).NotTo(HaveOccurred()) + + f.NewEchoDeployment() + + f.WaitForNginxConfiguration( + func(cfg string) bool { + return strings.Contains(cfg, "server_tokens on") + }) + + resp, _, _ := gorequest.New(). + Get(f.GetURL(framework.HTTP)). + Set("Host", "foo.bar.com"). + End() + Expect(resp.StatusCode).Should(Equal(http.StatusNotFound)) + }) +})