Skip to content

Commit

Permalink
Merge PR#11 'rogeruiz-add-richer-hsts-support' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
cf-buildpacks-eng committed Aug 17, 2017
2 parents e9da448 + 95c22c3 commit 71f6636
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/staticfile/finalize/data.go
Expand Up @@ -114,7 +114,7 @@ http {
{{end}}
{{if .HSTS}}
add_header Strict-Transport-Security "max-age=31536000";
add_header Strict-Transport-Security "max-age=31536000{{if .HSTSIncludeSubDomains}}; includeSubDomains{{end}}{{if .HSTSPreload}}; preload{{end}}";
{{end}}
{{if ne .LocationInclude ""}}
Expand Down
35 changes: 26 additions & 9 deletions src/staticfile/finalize/finalize.go
Expand Up @@ -14,15 +14,17 @@ import (
)

type Staticfile struct {
RootDir string `yaml:"root"`
HostDotFiles bool `yaml:"host_dot_files"`
LocationInclude string `yaml:"location_include"`
DirectoryIndex bool `yaml:"directory"`
SSI bool `yaml:"ssi"`
PushState bool `yaml:"pushstate"`
HSTS bool `yaml:"http_strict_transport_security"`
ForceHTTPS bool `yaml:"force_https"`
BasicAuth bool
RootDir string `yaml:"root"`
HostDotFiles bool `yaml:"host_dot_files"`
LocationInclude string `yaml:"location_include"`
DirectoryIndex bool `yaml:"directory"`
SSI bool `yaml:"ssi"`
PushState bool `yaml:"pushstate"`
HSTS bool `yaml:"http_strict_transport_security"`
HSTSIncludeSubDomains bool `yaml:"http_strict_transport_security_include_subdomains"`
HSTSPreload bool `yaml:"http_strict_transport_security_preload"`
ForceHTTPS bool `yaml:"force_https"`
BasicAuth bool
}

type YAML interface {
Expand Down Expand Up @@ -149,6 +151,16 @@ func (sf *Finalizer) LoadStaticfile() error {
sf.Log.BeginStep("Enabling HSTS")
conf.HSTS = true
}
case "http_strict_transport_security_include_subdomains":
if isEnabled {
sf.Log.BeginStep("Enabling HSTS includeSubDomains")
conf.HSTSIncludeSubDomains = true
}
case "http_strict_transport_security_preload":
if isEnabled {
sf.Log.BeginStep("Enabling HSTS Preload")
conf.HSTSPreload = true
}
case "force_https":
if isEnabled {
sf.Log.BeginStep("Enabling HTTPS redirect")
Expand All @@ -157,6 +169,11 @@ func (sf *Finalizer) LoadStaticfile() error {
}
}

if !conf.HSTS && (conf.HSTSIncludeSubDomains || conf.HSTSPreload) {
sf.Log.Warning("http_strict_transport_security is not enabled while http_strict_transport_security_include_subdomains or http_strict_transport_security_preload have been enabled.")
sf.Log.Protip("http_strict_transport_security_include_subdomains and http_strict_transport_security_preload do nothing without http_strict_transport_security enabled.", "http://docs.cloudfoundry.org/buildpacks/staticfile/index.html#strict-security")
}

authFile := filepath.Join(sf.BuildDir, "Staticfile.auth")
_, err = os.Stat(authFile)
if err == nil {
Expand Down
72 changes: 71 additions & 1 deletion src/staticfile/finalize/finalize_test.go
Expand Up @@ -135,6 +135,8 @@ var _ = Describe("Compile", func() {
Expect(finalizer.Config.SSI).To(Equal(false))
Expect(finalizer.Config.PushState).To(Equal(false))
Expect(finalizer.Config.HSTS).To(Equal(false))
Expect(finalizer.Config.HSTSIncludeSubDomains).To(Equal(false))
Expect(finalizer.Config.HSTSPreload).To(Equal(false))
Expect(finalizer.Config.ForceHTTPS).To(Equal(false))
Expect(finalizer.Config.BasicAuth).To(Equal(false))
})
Expand Down Expand Up @@ -237,14 +239,44 @@ var _ = Describe("Compile", func() {
(*hash)["http_strict_transport_security"] = "true"
})
})
It("sets pushstate", func() {
It("sets http_strict_transport_security", func() {
Expect(finalizer.Config.HSTS).To(Equal(true))
})
It("Logs", func() {
Expect(buffer.String()).To(Equal("-----> Enabling HSTS\n"))
})
})

Context("and sets http_strict_transport_security_include_subdomains", func() {
BeforeEach(func() {
mockYaml.EXPECT().Load(filepath.Join(buildDir, "Staticfile"), gomock.Any()).Do(func(_ string, hash *map[string]string) {
(*hash)["http_strict_transport_security_include_subdomains"] = "true"
})
})
It("sets http_strict_transport_security_include_subdomains", func() {
Expect(finalizer.Config.HSTSIncludeSubDomains).To(Equal(true))
Expect(finalizer.Config.HSTS).To(Equal(false))
})
It("Logs", func() {
Expect(buffer.String()).To(ContainSubstring("-----> Enabling HSTS includeSubDomains\n"))
})
})

Context("and sets http_strict_transport_security_preload", func() {
BeforeEach(func() {
mockYaml.EXPECT().Load(filepath.Join(buildDir, "Staticfile"), gomock.Any()).Do(func(_ string, hash *map[string]string) {
(*hash)["http_strict_transport_security_preload"] = "true"
})
})
It("sets http_strict_transport_security_preload", func() {
Expect(finalizer.Config.HSTSPreload).To(Equal(true))
Expect(finalizer.Config.HSTS).To(Equal(false))
})
It("Logs", func() {
Expect(buffer.String()).To(ContainSubstring("-----> Enabling HSTS Preload\n"))
})
})

Context("and sets force_https", func() {
BeforeEach(func() {
mockYaml.EXPECT().Load(filepath.Join(buildDir, "Staticfile"), gomock.Any()).Do(func(_ string, hash *map[string]string) {
Expand Down Expand Up @@ -622,6 +654,31 @@ var _ = Describe("Compile", func() {
})
})

Context("http_strict_transport_security and http_strict_transport_security_include_subdomain is set in staticfile", func() {
BeforeEach(func() {
staticfile.HSTS = true
staticfile.HSTSIncludeSubDomains = true
})
It("it adds the HSTS header", func() {
data, err = ioutil.ReadFile(filepath.Join(buildDir, "nginx", "conf", "nginx.conf"))
Expect(err).To(BeNil())
Expect(string(data)).To(ContainSubstring(`add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";`))
})
})

Context("http_strict_transport_security, http_strict_transport_security_include_subdomain, and http_strict_transport_security_preload is set in staticfile", func() {
BeforeEach(func() {
staticfile.HSTS = true
staticfile.HSTSIncludeSubDomains = true
staticfile.HSTSPreload = true
})
It("it adds the HSTS header", func() {
data, err = ioutil.ReadFile(filepath.Join(buildDir, "nginx", "conf", "nginx.conf"))
Expect(err).To(BeNil())
Expect(string(data)).To(ContainSubstring(`add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";`))
})
})

Context("http_strict_transport_security is NOT set in staticfile", func() {
BeforeEach(func() {
staticfile.HSTS = false
Expand All @@ -633,6 +690,19 @@ var _ = Describe("Compile", func() {
})
})

Context("http_strict_transport_security is NOT set in staticfile, but http_strict_transport_security_preload or http_strict_transport_security_include_subdomain are set in staticfile", func() {
BeforeEach(func() {
staticfile.HSTS = false
staticfile.HSTSIncludeSubDomains = true
staticfile.HSTSPreload = true
})
It("it does not add the HSTS header", func() {
data, err = ioutil.ReadFile(filepath.Join(buildDir, "nginx", "conf", "nginx.conf"))
Expect(err).To(BeNil())
Expect(string(data)).NotTo(ContainSubstring(`add_header Strict-Transport-Security "max-age=31536000";`))
})
})

Context("force_https is set in staticfile", func() {
BeforeEach(func() {
staticfile.ForceHTTPS = true
Expand Down

0 comments on commit 71f6636

Please sign in to comment.