forked from projectcontour/contour
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
internal/contour: add SecretCache and link to grpc
Addresses the second high-level design bullet point, creating a SecretCache to be used by Contour to internally identify any changes. The cache is also registered as a reource type for the gRPC server, allowing it to respond to requests. Updates: projectcontour#898 Signed-off-by: Matt Alberts <[email protected]>
Matt Alberts
committed
Apr 30, 2019
1 parent
7b7a36e
commit c7ba7f4
Showing
9 changed files
with
833 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// Copyright © 2018 Heptio | ||
// 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 contour | ||
|
||
import ( | ||
"sync" | ||
|
||
"github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" | ||
"github.com/gogo/protobuf/proto" | ||
"github.com/heptio/contour/internal/dag" | ||
"github.com/heptio/contour/internal/envoy" | ||
) | ||
|
||
// SecretCache manages the contents of the gRPC SDS cache. | ||
type SecretCache struct { | ||
mu sync.Mutex | ||
values map[string]*auth.Secret | ||
waiters []chan int | ||
last int | ||
} | ||
|
||
// Register registers ch to receive a value when Notify is called. | ||
// The value of last is the count of the times Notify has been called on this Cache. | ||
// It functions of a sequence counter, if the value of last supplied to Register | ||
// is less than the Cache's internal counter, then the caller has missed at least | ||
// one notification and will fire immediately. | ||
// | ||
// Sends by the broadcaster to ch must not block, therefor ch must have a capacity | ||
// of at least 1. | ||
func (c *SecretCache) Register(ch chan int, last int) { | ||
c.mu.Lock() | ||
defer c.mu.Unlock() | ||
|
||
if last < c.last { | ||
// notify this channel immediately | ||
ch <- c.last | ||
return | ||
} | ||
c.waiters = append(c.waiters, ch) | ||
} | ||
|
||
// Update replaces the contents of the cache with the supplied map. | ||
func (c *SecretCache) Update(v map[string]*auth.Secret) { | ||
c.mu.Lock() | ||
defer c.mu.Unlock() | ||
|
||
c.values = v | ||
c.notify() | ||
} | ||
|
||
// notify notifies all registered waiters that an event has occurred. | ||
func (c *SecretCache) notify() { | ||
c.last++ | ||
|
||
for _, ch := range c.waiters { | ||
ch <- c.last | ||
} | ||
c.waiters = c.waiters[:0] | ||
} | ||
|
||
// Values returns a slice of the value stored in the cache. | ||
func (c *SecretCache) Values(filter func(string) bool) []proto.Message { | ||
c.mu.Lock() | ||
values := make([]proto.Message, 0, len(c.values)) | ||
for _, v := range c.values { | ||
if filter(v.Name) { | ||
values = append(values, v) | ||
} | ||
} | ||
c.mu.Unlock() | ||
return values | ||
} | ||
|
||
type secretVisitor struct { | ||
secrets map[string]*auth.Secret | ||
} | ||
|
||
// visitSecrets produces a map of *auth.Secret | ||
func visitSecrets(root dag.Vertex) map[string]*auth.Secret { | ||
sv := secretVisitor{ | ||
secrets: make(map[string]*auth.Secret), | ||
} | ||
sv.visit(root) | ||
return sv.secrets | ||
} | ||
|
||
func (v *secretVisitor) visit(vertex dag.Vertex) { | ||
switch svh := vertex.(type) { | ||
case *dag.SecureVirtualHost: | ||
if svh.Secret != nil { | ||
name := envoy.Secretname(svh.Secret) | ||
if _, ok := v.secrets[name]; !ok { | ||
s := envoy.Secret(svh.Secret) | ||
v.secrets[s.Name] = s | ||
} | ||
} | ||
default: | ||
vertex.Visit(v.visit) | ||
} | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package envoy | ||
|
||
import ( | ||
"crypto/sha1" | ||
"fmt" | ||
|
||
"github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" | ||
"github.com/envoyproxy/go-control-plane/envoy/api/v2/core" | ||
"github.com/heptio/contour/internal/dag" | ||
) | ||
|
||
// Secretname returns the name of the SDS secret for this secret. | ||
func Secretname(s *dag.Secret) string { | ||
hash := sha1.Sum(s.Cert()) | ||
ns := s.Namespace() | ||
name := s.Name() | ||
return hashname(60, ns, name, fmt.Sprintf("%x", hash[:5])) | ||
} | ||
|
||
// Secret creates new v2auth.Secret from secret. | ||
func Secret(s *dag.Secret) *auth.Secret { | ||
return &auth.Secret{ | ||
Name: Secretname(s), | ||
Type: &auth.Secret_TlsCertificate{ | ||
TlsCertificate: &auth.TlsCertificate{ | ||
PrivateKey: &core.DataSource{ | ||
Specifier: &core.DataSource_InlineBytes{ | ||
InlineBytes: s.PrivateKey(), | ||
}, | ||
}, | ||
CertificateChain: &core.DataSource{ | ||
Specifier: &core.DataSource_InlineBytes{ | ||
InlineBytes: s.Cert(), | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package envoy | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/envoyproxy/go-control-plane/envoy/api/v2/auth" | ||
"github.com/envoyproxy/go-control-plane/envoy/api/v2/core" | ||
"github.com/google/go-cmp/cmp" | ||
"github.com/heptio/contour/internal/dag" | ||
"k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
func TestSecret(t *testing.T) { | ||
tests := map[string]struct { | ||
secret *dag.Secret | ||
want *auth.Secret | ||
}{ | ||
"simple secret": { | ||
secret: &dag.Secret{ | ||
Object: &v1.Secret{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "simple", | ||
Namespace: "default", | ||
}, | ||
Data: map[string][]byte{ | ||
v1.TLSCertKey: []byte("cert"), | ||
v1.TLSPrivateKeyKey: []byte("key"), | ||
}, | ||
}, | ||
}, | ||
want: &auth.Secret{ | ||
Name: "default/simple/cd1b506996", | ||
Type: &auth.Secret_TlsCertificate{ | ||
TlsCertificate: &auth.TlsCertificate{ | ||
PrivateKey: &core.DataSource{ | ||
Specifier: &core.DataSource_InlineBytes{ | ||
InlineBytes: []byte("key"), | ||
}, | ||
}, | ||
CertificateChain: &core.DataSource{ | ||
Specifier: &core.DataSource_InlineBytes{ | ||
InlineBytes: []byte("cert"), | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
for name, tc := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
got := Secret(tc.secret) | ||
if diff := cmp.Diff(tc.want, got); diff != "" { | ||
t.Fatal(diff) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestSecretname(t *testing.T) { | ||
tests := map[string]struct { | ||
secret *dag.Secret | ||
want string | ||
}{ | ||
"simple": { | ||
secret: &dag.Secret{ | ||
Object: &v1.Secret{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "simple", | ||
Namespace: "default", | ||
}, | ||
Data: map[string][]byte{ | ||
v1.TLSCertKey: []byte("cert"), | ||
v1.TLSPrivateKeyKey: []byte("key"), | ||
}, | ||
}, | ||
}, | ||
want: "default/simple/cd1b506996", | ||
}, | ||
"far too long": { | ||
secret: &dag.Secret{ | ||
Object: &v1.Secret{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "must-be-in-want-of-a-wife", | ||
Namespace: "it-is-a-truth-universally-acknowledged-that-a-single-man-in-possession-of-a-good-fortune", | ||
}, | ||
Data: map[string][]byte{ | ||
v1.TLSCertKey: []byte("cert"), | ||
v1.TLSPrivateKeyKey: []byte("key"), | ||
}, | ||
}, | ||
}, | ||
want: "it-is-a-truth-7e164b/must-be-in-wa-7e164b/cd1b506996", | ||
}, | ||
} | ||
|
||
for name, tc := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
got := Secretname(tc.secret) | ||
if diff := cmp.Diff(tc.want, got); diff != "" { | ||
t.Fatal(diff) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters