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

Echo.StartTLSFromFile: Add function that loads key pair from strings #1277

Merged
merged 1 commit into from
Feb 15, 2019
Merged

Echo.StartTLSFromFile: Add function that loads key pair from strings #1277

merged 1 commit into from
Feb 15, 2019

Conversation

mbana
Copy link
Contributor

@mbana mbana commented Feb 8, 2019

echo.go - Echo. StartTLSFromFile:

  • Add function that loads key pair from strings.

echo_test.go - Echo. StartTLSFromFile:

  • Add test TestEchoStartTLSFromFile.

@codecov
Copy link

codecov bot commented Feb 8, 2019

Codecov Report

Merging #1277 into master will increase coverage by 0.2%.
The diff coverage is 93.75%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master    #1277     +/-   ##
=========================================
+ Coverage   81.78%   81.99%   +0.2%     
=========================================
  Files          26       26             
  Lines        1933     1944     +11     
=========================================
+ Hits         1581     1594     +13     
+ Misses        243      242      -1     
+ Partials      109      108      -1
Impacted Files Coverage Δ
echo.go 88.15% <93.75%> (+1.19%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 8896575...12ba62c. Read the comment docs.

echo.go Outdated
// StartTLSFromFile starts an HTTPS server.
// If `fromFile` is `true`: `cert` and `key` are paths to files that contain the certificate and key.
// If `fromFile` is `false`: `cert` and `key` contain the certificate and key.
func (e *Echo) StartTLSFromFile(address string, cert, key string, fromFile bool) (err error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name is misleading. It loads either from file or from the strings provided.

It would be nice if we could avoid adding another method to start TLS... I generally avoid using interface{} as much as possible, but can't help wondering if it wouldn't be appropriate here. If we change the signature of StartTLS() to StartTLS(address string, certFile, keyFile interface{}) then the callers could submit either string (which would mean path) or []byte (which would mean key/cert content). It would be backward compatible, it would continue to accept strings as input. But it would also support the new feature. Thoughts @mbana @im-kulikov @vishr ?

Either way, this sounds like a very useful feature :-) Now one can feed it straight from AWS Parameter Store or from Vault :-)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

func (e *Echo) StartTLSFromFile(address string, key string, reader io.Reader) (err error) {

mb this is more useful?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardly @im-kulikov as https://golang.org/pkg/crypto/tls/#Certificate only takes in either path to files or content of certs (but no io.Reader). So asking for that param means both more work for callers and more fork for the function itself, makes little sense.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can read from io.Reader key and cert and pass it to X509KeyPair..

https://golang.org/pkg/crypto/tls/#X509KeyPair

func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) {

Copy link
Contributor

@im-kulikov im-kulikov Feb 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something like this:

func (e *Echo) StartTLSFromReader(address string, key, cert io.Reader) (err error) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you. now I see what you mean.

Copy link
Contributor

@alexaandru alexaandru Feb 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great then :)

Also, giving it a 2nd look, I would actually introduce an unexported function to clean it up further:

func (e *Echo) StartTLS(address string, certFile, keyFile interface{}) (err error) {
    var cert []byte
    if cert, err = filepathOrContent(certFile); err != nil {
        return
    }

    var key []byte
    if key, err = filepathOrContent(keyFile); err != nil {
        return
    }

    s := e.TLSServer
    s.TLSConfig = new(tls.Config)
    s.TLSConfig.Certificates = make([]tls.Certificate, 1)
    if s.TLSConfig.Certificates[0], err = tls.X509KeyPair(cert, key); err != nil {
        return
    }
	
    return e.startTLS(address)
}

func filepathOrContent(fileOrContent interface{}) (content []byte, err error) {
    switch v := fileOrContent.(type) {
    case string:
        return ioutil.ReadFile(v)
    case []byte:
        return v, nil
    default:
        return nil, fmt.Errorf("invalid cert type, must be string or []byte")
    }
}

Yeah, I like this better.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sgtm

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @alexaandru that looks good. I was worried about breaking backwards compatibility hence I introduced the new function.

echo_test.go Outdated
require.NoError(err)

// Prevent the test to fail after closing the servers
if err := e.StartTLS(":0", []byte(cert), []byte(key)); err != http.ErrServerClosed {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://golang.org/pkg/io/ioutil/#ReadFile

func ReadFile(filename string) ([]byte, error)

[]byte(cert), []byte(key) is unnecessary conversion

Copy link
Contributor

@im-kulikov im-kulikov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small fix, see above

@mbana
Copy link
Contributor Author

mbana commented Feb 11, 2019

small fix, see above

See latest PR, I did a force push (sorry).
Thanks

echo.go Outdated
@@ -269,6 +270,7 @@ var (
ErrRendererNotRegistered = errors.New("renderer not registered")
ErrInvalidRedirectCode = errors.New("invalid redirect status code")
ErrCookieNotFound = errors.New("cookie not found")
ErrInvalidCertType = errors.New("invalid cert type, must be string or []byte")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

invalid cert or key type, must be string or []byte

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

echo_test.go Outdated
expectedErr error
name string
}
testCases := []testCase{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mb:

testCases := []struct {
 		cert        interface{}
 		key         interface{}
 		expectedErr error
 		name        string
 	}{
 	//...
 	}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

key: 1,
expectedErr: ErrInvalidCertType,
name: `InvalidCertAndKeyTypes`,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pls add:

{
 			cert:        "_fixture/certs/cert.pem",
 			key:         "_fixture/certs/key.pem",
 			expectedErr: nil,
 			name:        `ValidCertAndKeyFilePath`,
 		}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Copy link
Contributor

@im-kulikov im-kulikov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and quite a little bit fix

If `certFile` or `keyFile` is `string` the values are treated as file paths.
If `certFile` or `keyFile` is `[]byte` the values are treated as the certificate or key as-is.
Copy link
Contributor

@im-kulikov im-kulikov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 great job! Thanks

@alexaandru
Copy link
Contributor

Looks good! :)

@mbana
Copy link
Contributor Author

mbana commented Feb 14, 2019

Thanks a lot, folks. What shall I do now? I cannot see a merge button.

@im-kulikov
Copy link
Contributor

@alexaandru / @vishr can we merge or you wait for something else?

@vishr vishr merged commit 8716acb into labstack:master Feb 15, 2019
@vishr
Copy link
Member

vishr commented Feb 15, 2019

Thanks guys!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants