Skip to content

ca: when the Root CA is updated in the security config, update all TLS creds too#1983

Merged
diogomonica merged 1 commit into
moby:masterfrom
cyli:update-root-ca-updates-tls-creds
Mar 2, 2017
Merged

ca: when the Root CA is updated in the security config, update all TLS creds too#1983
diogomonica merged 1 commit into
moby:masterfrom
cyli:update-root-ca-updates-tls-creds

Conversation

@cyli
Copy link
Copy Markdown
Contributor

@cyli cyli commented Feb 24, 2017

So that both can use the new root CA pool to validate peers.

@cyli cyli changed the title When the Root CA is updated in the security config, update client/server creds too ca: when the Root CA is updated in the security config, update client/server creds too Feb 24, 2017
Comment thread ca/config.go Outdated
if s.ClientTLSCreds != nil {
previousConfig := s.ClientTLSCreds.Config()
// can't error because we know for sure the root pool is valid
newConfig, _ := NewClientTLSConfig(&previousConfig.Certificates[0], rootCA.Pool, previousConfig.ServerName)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we know for sure that previousConfig.Certificates has at least one item?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is there a possibility of a race here? Say the node's certificate gets renewed at the same moment, and there's a call to LoadNewTLSConfig in these calls to Config and LoadNewTLSConfig. Wouldn't we overwrite the new node certificate?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@aaronlehmann Good point - I guess the lock needs to be on the mutable TLS object.

@codecov-io
Copy link
Copy Markdown

codecov-io commented Feb 24, 2017

Codecov Report

Merging #1983 into master will increase coverage by 0.17%.
The diff coverage is 92.3%.

@@            Coverage Diff             @@
##           master    #1983      +/-   ##
==========================================
+ Coverage   53.69%   53.86%   +0.17%     
==========================================
  Files         109      109              
  Lines       18925    18943      +18     
==========================================
+ Hits        10161    10203      +42     
+ Misses       7538     7501      -37     
- Partials     1226     1239      +13

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 a52e9c8...598a7ed. Read the comment docs.

@cyli cyli force-pushed the update-root-ca-updates-tls-creds branch 2 times, most recently from dd0743c to b043029 Compare February 24, 2017 03:45
Comment thread ca/transport.go Outdated
func (c *MutableTLSCreds) UpdateCAs(rootCAs, clientCAs *x509.CertPool) {
c.Lock()
defer c.Unlock()
// TODO(cyli): on upgrade to go 1.8.x, use c.config.Clone() instead
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Clone exists in 1.7.

Would you mind switching to it before merging?

AFAIK there's no reason we need to support Go 1.6. @vdemeester do you know if there is?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hm... do I have something horribly misconfigured?

$ go test -race github.com/docker/swarmkit/ca
ca/transport.go:142: c.config.Clone undefined (type *tls.Config has no field or method Clone, but does have tls.clone)

$  go version
go version go1.7.4 darwin/amd64

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

https://github.com/golang/go/blob/release-branch.go1.7/src/crypto/tls/common.go#L426 seems to only have Config.clone(), but https://github.com/golang/go/blob/release-branch.go1.8/src/crypto/tls/common.go#L550 has the exported function (I could just be missing an exported function in 1.7 in a different file, though)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I looked for Clone on both branches to verify, but did not notice it's unexported in 1.7.

I remember https://github.com/docker/docker/blob/master/pkg/tlsconfig dealing with this, and I see this was back in September. I thought it happened before Go 1.7 was released. Apparently it was right after. My apologies.

Anyway, would you mind vendoring/importing github.com/docker/docker/pkg/tlsconfig in this PR?

Copy link
Copy Markdown
Contributor Author

@cyli cyli Feb 24, 2017

Choose a reason for hiding this comment

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

Not at all - as I've said before, my machine is haunted :) And go vet still produces errors on my machine that no one else seems to be able to replicate so I totally would believe something is wrong with my setup.

And sure, will do.

Comment thread ca/config.go Outdated
}

s.rootCA = &rootCA
return err
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: return nil?

@cyli cyli force-pushed the update-root-ca-updates-tls-creds branch from a4b6560 to 21dbca4 Compare February 24, 2017 18:30
@cyli cyli mentioned this pull request Feb 28, 2017
10 tasks
@cyli cyli force-pushed the update-root-ca-updates-tls-creds branch from 21dbca4 to 89f5ff4 Compare February 28, 2017 01:51
@cyli cyli changed the title ca: when the Root CA is updated in the security config, update client/server creds too ca: when the Root CA is updated in the security config, update all TLS creds too Feb 28, 2017
Comment thread ca/certificates.go Outdated
return
}

return
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

How about return cfcsr.ParseRequest(req) for clarity?

Comment thread ca/config.go Outdated
// ExternalCA returns the external CA.
func (s *SecurityConfig) ExternalCA() *ExternalCA {
s.mu.Lock()
defer s.mu.Unlock()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't believe it's necessary to hold this lock. s.externalCA seems to be set when the SecurityConfig is created, and never changed to point to anything else. updateCluster uses this field without holding the lock.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point, thanks!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we want to be conservative in both places?

@aaronlehmann
Copy link
Copy Markdown
Collaborator

Needs a rebase

…erver, client, and external CA

TLS credentials all also use the new root pool.

Signed-off-by: cyli <ying.li@docker.com>
@cyli cyli force-pushed the update-root-ca-updates-tls-creds branch from 89f5ff4 to 598a7ed Compare March 1, 2017 02:59
Comment thread ca/config.go
}

// ExternalCA returns the external CA.
func (s *SecurityConfig) ExternalCA() *ExternalCA {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we need locking?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Comment thread ca/transport.go
func (c *MutableTLSCreds) UpdateCAs(rootCAs, clientCAs *x509.CertPool) {
c.Lock()
defer c.Unlock()
config := tlsconfig.Clone(c.config)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why do we need to clone instead of directly modifying it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I tried that originally, but it's not really safe to modify a tls.Config while it's being used I think. I ended up with a data race in the tests, since a tls.Config stores some handshake/session state. The comment for tls.Config contains:

After one has been passed to a TLS function it must not be modified.

@diogomonica diogomonica merged commit 1dfa1a9 into moby:master Mar 2, 2017
@cyli cyli deleted the update-root-ca-updates-tls-creds branch March 2, 2017 00:30
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.

4 participants