Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Configuring certificate issuers for apps #232

Merged
merged 5 commits into from
Oct 17, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
adding unit tests
gvicentin authored and wpjunior committed Oct 15, 2024
commit cdedc7ddd3c60cde0ea7b5b8eece56535af8b1c5
8 changes: 6 additions & 2 deletions tsuru/client/certificate.go
Original file line number Diff line number Diff line change
@@ -87,7 +87,7 @@ func (c *CertificateSet) Run(context *cmd.Context) error {
return err
}
defer response.Body.Close()
fmt.Fprintln(context.Stdout, "Successfully created the certificated.")
fmt.Fprintln(context.Stdout, "Successfully created the certificate.")
return nil
}

@@ -214,6 +214,10 @@ func (c *CertificateList) Run(context *cmd.Context) error {
for router, routerCerts := range appCerts.RouterCertificates {
fmt.Fprintf(context.Stdout, "%s:\n", router)
for cname, cnameCert := range routerCerts.CNameCertificates {
if cnameCert.Certificate == "" {
fmt.Fprintf(context.Stdout, "%s:\nNo certificate.", cname)
continue
}
fmt.Fprintf(context.Stdout, "%s:\n%s", cname, cnameCert.Certificate)
}
}
@@ -398,7 +402,7 @@ func (c *CertificateIssuerSet) Run(context *cmd.Context) error {
}
defer response.Body.Close()

fmt.Fprintln(context.Stdout, "Successfully created the certificated issuer.")
fmt.Fprintln(context.Stdout, "Successfully created the certificate issuer.")
return nil
}

152 changes: 122 additions & 30 deletions tsuru/client/certificate_test.go
Original file line number Diff line number Diff line change
@@ -12,7 +12,6 @@ import (
"strings"
"time"

"github.com/tsuru/tsuru-client/tsuru/formatter"
"github.com/tsuru/tsuru/cmd"
"github.com/tsuru/tsuru/cmd/cmdtest"
check "gopkg.in/check.v1"
@@ -49,7 +48,7 @@ func (s *S) TestCertificateSetRunSuccessfully(c *check.C) {
c.Assert(command.cname, check.Equals, "app.io")
err := command.Run(&context)
c.Assert(err, check.IsNil)
c.Assert(stdout.String(), check.Equals, "Successfully created the certificated.\n")
c.Assert(stdout.String(), check.Equals, "Successfully created the certificate.\n")
}

func (s *S) TestCertificateSetRunCerticateNotFound(c *check.C) {
@@ -124,33 +123,53 @@ func (s *S) TestCertificateListRunSuccessfully(c *check.C) {
Stderr: &stderr,
}
requestCount := 0
certMap := map[string]map[string]string{
"ingress-router": {
"myapp.io": s.mustReadFileString(c, "./testdata/cert/server.crt"),
"myapp.other.io": "",
},
"a-new-router": {
"myapp.io": s.mustReadFileString(c, "./testdata/cert/server.crt"),
certData := s.mustReadFileString(c, "./testdata/cert/server.crt")
appCert := appCertificate{
RouterCertificates: map[string]routerCertificate{
"ingress-router": {
CNameCertificates: map[string]cnameCertificate{
"myapp.io": {
Certificate: certData,
Issuer: "lets-encrypt",
},
"myapp.other.io": {
Certificate: "",
},
},
},
"a-new-router": {
CNameCertificates: map[string]cnameCertificate{
"myapp.io": {
Certificate: certData,
},
},
},
},
}
data, err := json.Marshal(certMap)
data, err := json.Marshal(appCert)
c.Assert(err, check.IsNil)
expectedDate, err := time.Parse("2006-01-02 15:04:05", "2027-01-10 20:33:11")
expectedNotBefore, err := time.Parse("2006-01-02 15:04:05", "2017-01-12 20:33:11")
expectedNotAfter, err := time.Parse("2006-01-02 15:04:05", "2027-01-10 20:33:11")
c.Assert(err, check.IsNil)
datestr := formatter.Local(expectedDate).Format("2006-01-02 15:04:05")
expected := `+----------------+----------------+---------------------+----------------------------+----------------------------+
| Router | CName | Expires | Issuer | Subject |
+----------------+----------------+---------------------+----------------------------+----------------------------+
| a-new-router | myapp.io | ` + datestr + ` | C=BR; ST=Rio de Janeiro; | C=BR; ST=Rio de Janeiro; |
| | | | L=Rio de Janeiro; O=Tsuru; | L=Rio de Janeiro; O=Tsuru; |
| | | | CN=app.io | CN=app.io |
+----------------+----------------+---------------------+----------------------------+----------------------------+
| ingress-router | myapp.io | ` + datestr + ` | C=BR; ST=Rio de Janeiro; | C=BR; ST=Rio de Janeiro; |
| | | | L=Rio de Janeiro; O=Tsuru; | L=Rio de Janeiro; O=Tsuru; |
| | | | CN=app.io | CN=app.io |
+----------------+----------------+---------------------+----------------------------+----------------------------+
| ingress-router | myapp.other.io | - | - | - |
+----------------+----------------+---------------------+----------------------------+----------------------------+
notBeforeStr := expectedNotBefore.UTC().Format(time.RFC3339)
notAfterStr := expectedNotAfter.UTC().Format(time.RFC3339)
expected := `+----------------+----------------------------+-----------------------+----------------------+
| Router | CName | Public Key Info | Certificate Validity |
+----------------+----------------------------+-----------------------+----------------------+
| a-new-router | myapp.io | Algorithm | Not before |
| | | RSA | ` + notBeforeStr + ` |
| | | | |
| | | Key size (in bits) | Not after |
| | | 2048 | ` + notAfterStr + ` |
+----------------+----------------------------+-----------------------+----------------------+
| ingress-router | myapp.io | Algorithm | Not before |
| | managed by: cert-manager | RSA | ` + notBeforeStr + ` |
| | issuer: lets-encrypt | | |
| | | Key size (in bits) | Not after |
| | | 2048 | ` + notAfterStr +` |
+----------------+----------------------------+-----------------------+----------------------+
| ingress-router | myapp.other.io | failed to decode data | - |
+----------------+----------------------------+-----------------------+----------------------+
`
trans := &cmdtest.ConditionalTransport{
Transport: cmdtest.Transport{
@@ -181,13 +200,22 @@ func (s *S) TestCertificateListRawRunSuccessfully(c *check.C) {
}
requestCount := 0
certData := s.mustReadFileString(c, "./testdata/cert/server.crt")
certMap := map[string]map[string]string{
"ingress-router": {
"myapp.io": certData,
"myapp.other.io": "",
appCert := appCertificate{
RouterCertificates: map[string]routerCertificate{
"ingress-router": {
CNameCertificates: map[string]cnameCertificate{
"myapp.io": {
Certificate: certData,
Issuer: "lets-encrypt",
},
"myapp.other.io": {
Certificate: "",
},
},
},
},
}
data, err := json.Marshal(certMap)
data, err := json.Marshal(appCert)
c.Assert(err, check.IsNil)
trans := &cmdtest.ConditionalTransport{
Transport: cmdtest.Transport{
@@ -210,3 +238,67 @@ func (s *S) TestCertificateListRawRunSuccessfully(c *check.C) {
c.Assert(strings.Contains(stdout.String(), "myapp.io:\n"+certData), check.Equals, true)
c.Assert(requestCount, check.Equals, 1)
}

func (s *S) TestCertificateIssuerSetInfo(c *check.C) {
c.Assert((&CertificateIssuerSet{}).Info(), check.NotNil)
}

func (s *S) TestCertificateIssuerSetRunSuccessfully(c *check.C) {
var stdout, stderr bytes.Buffer
context := cmd.Context{
Stdout: &stdout,
Stderr: &stderr,
Args: []string{
"lets-encrypt",
},
}
trans := &cmdtest.ConditionalTransport{
Transport: cmdtest.Transport{Status: http.StatusNoContent},
CondFunc: func(req *http.Request) bool {
url := strings.HasSuffix(req.URL.Path, "/apps/secret/certissuer")
method := req.Method == http.MethodPut
cname := req.FormValue("cname") == "app.io"
issuer := req.FormValue("issuer") == "lets-encrypt"
return url && method && cname && issuer
},
}
s.setupFakeTransport(trans)
command := CertificateIssuerSet{}
command.Flags().Parse(true, []string{"-a", "secret", "-c", "app.io"})
c.Assert(command.cname, check.Equals, "app.io")
err := command.Run(&context)
c.Assert(err, check.IsNil)
c.Assert(stdout.String(), check.Equals, "Successfully created the certificate issuer.\n")
}

func (s *S) TestCertificateIssuerUnsetInfo(c *check.C) {
c.Assert((&CertificateIssuerUnset{}).Info(), check.NotNil)
}

func (s *S) TestCertificateIssuerUnsetRunSuccessfully(c *check.C) {
var stdout, stderr bytes.Buffer
context := cmd.Context{
Stdout: &stdout,
Stderr: &stderr,
}
requestCount := 0
trans := &cmdtest.ConditionalTransport{
Transport: cmdtest.Transport{Status: http.StatusNoContent},
CondFunc: func(req *http.Request) bool {
requestCount++
url := strings.HasSuffix(req.URL.Path, "/apps/secret/certissuer")
method := req.Method == http.MethodDelete
cname := req.FormValue("cname") == "app.io"

return url && method && cname
},
}
s.setupFakeTransport(trans)
command := CertificateIssuerUnset{}
command.Flags().Parse(true, []string{"-a", "secret", "-c", "app.io"})
c.Assert(command.cname, check.Equals, "app.io")
err := command.Run(&context)
c.Assert(err, check.IsNil)
c.Assert(stdout.String(), check.Equals, "Certificate issuer removed.\n")
c.Assert(requestCount, check.Equals, 1)
}