Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
6e6dd26
new SensorComponent to keep local scanner secrets up to date
Feb 8, 2022
84816d9
fix style
Feb 8, 2022
16b5d08
fetch sensor deployment starting with sensor pod owner name
Feb 8, 2022
dfe2121
add some tests
Feb 8, 2022
d583faa
fix style
Feb 8, 2022
d3f9d15
wip adapting to changes in repo and refresher
Feb 10, 2022
b52c3f5
rebase
Feb 15, 2022
40da452
rebase tests
Feb 15, 2022
60844b5
add test for fetch sensor deployment
Feb 15, 2022
43be8fe
complete tests for start
Feb 15, 2022
d6e956d
complete tests
Feb 15, 2022
d4f7ced
improve comment
Feb 15, 2022
39c6b83
launch cert refresher if feature flag enabled
Feb 15, 2022
efc86b6
minor refactor
Feb 15, 2022
d13bf17
build sensor deployment owner reference from replica set owner
Feb 17, 2022
679e31e
fix typo
Feb 17, 2022
687e7f3
stop on start abort
Feb 17, 2022
24e6a07
check secret ownership in refresher, to do it with retries
Feb 17, 2022
295f460
fix cap of fetchSensorDeploymentOwnerRefBackoff
Feb 17, 2022
525167c
always log error on abort
Feb 21, 2022
e4ad886
do not hardcode api version and kind in owner ref of replica set owner
Feb 21, 2022
37f8d85
fetch deployment owner ref starting with sensor name
Feb 21, 2022
f5ecb77
fix function header indentation
Feb 22, 2022
267875b
adjust logging levels
Feb 22, 2022
93f1b0f
rename supplier to getter
Feb 22, 2022
51d4d29
improve comments
Feb 22, 2022
fe0ae6a
minor code formatting
Feb 22, 2022
27ae534
wait for assertion on process message
Feb 22, 2022
e3a7381
improve naming of test struct
Feb 22, 2022
07ee96f
use longer variable names
Feb 22, 2022
8b3f596
improve logging
Feb 22, 2022
c47fe40
do not stop Sensor start when this component fails to start
Feb 22, 2022
7cbf035
abort start for bundle installations
Feb 22, 2022
9d2db92
add integration test for happy path
Feb 23, 2022
41e94fc
check wrapped errors not only outer error
Feb 23, 2022
0578fbd
extend happy path integ test to corrupted secrets
Feb 23, 2022
707bb64
test cert issue retries on integration test
Feb 23, 2022
0565a66
add public method to check if ticker was stopped
Feb 23, 2022
fb4af92
give priority to ErrUnexpectedSecretsOwner on get secrets call
Feb 23, 2022
aef8dfa
add integ test for tls issuer stop on wrong secrets owner
Feb 23, 2022
832fa82
account for eventual consistency of mock k8s client
Feb 23, 2022
8a3173c
add message to assertion
Feb 24, 2022
41218cf
decide component launch based on managedBy on CreateSensor
Feb 24, 2022
bb322d7
use deny list instead of allow list for tls issuer component enablement
Feb 24, 2022
c4c2b07
use certificates for both scanner and scanner db in integ test
Feb 24, 2022
7de21b0
add message to assertion derived from a poll, ot make it more clear
Feb 24, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: ROX_CENTRAL_ENDPOINT
value: {{ ._rox.centralEndpoint }}
- name: ROX_ADVERTISED_ENDPOINT
Expand Down
3 changes: 3 additions & 0 deletions pkg/centralsensor/caps_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@ const (

// AuditLogEventsCap identifies the capability to handle audit log event detection.
AuditLogEventsCap SensorCapability = "AuditLogEvents"

// LocalScannerCredentialsRefresh identifies the capability to maintain the Local scanner TLS credentials refreshed.
LocalScannerCredentialsRefresh SensorCapability = "LocalScannerCredentialsRefresh"
)
10 changes: 8 additions & 2 deletions pkg/concurrency/retry_ticker.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var (
type RetryTicker interface {
Start() error
Stop()
Stopped() bool
}

type tickFunc func(ctx context.Context) (timeToNextTick time.Duration, err error)
Expand Down Expand Up @@ -64,7 +65,7 @@ type retryTickerImpl struct {
// - ErrStartedTimer is returned if the timer was already started.
// - ErrStoppedTimer is returned if the timer was stopped.
func (t *retryTickerImpl) Start() error {
if t.stopFlag.Get() {
if t.Stopped() {
return ErrStoppedTimer
}
if t.getTickTimer() != nil {
Expand All @@ -82,13 +83,18 @@ func (t *retryTickerImpl) Stop() {
t.setTickTimer(nil)
}

// Stopped returns true if this RetryTicker has been stopped, otherwise returns false.
func (t *retryTickerImpl) Stopped() bool {
return t.stopFlag.Get()
}

func (t *retryTickerImpl) scheduleTick(timeToTick time.Duration) {
t.setTickTimer(t.scheduler(timeToTick, func() {
ctx, cancel := context.WithTimeout(context.Background(), t.timeout)
defer cancel()

nextTimeToTick, tickErr := t.doFunc(ctx)
if t.stopFlag.Get() {
if t.Stopped() {
// ticker was stopped while tick function was running.
return
}
Expand Down
7 changes: 5 additions & 2 deletions sensor/kubernetes/localscanner/cert_refresher.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func refreshCertificates(ctx context.Context, requestCertificates requestCertifi
timeToNextRefresh, err = ensureCertificatesAreFresh(ctx, requestCertificates, getCertsRenewalTime, repository)
if err != nil {
if errors.Is(err, ErrUnexpectedSecretsOwner) {
log.Errorf("stopping automatic refresh of %s: %s", certsDescription, err)
log.Errorf("non-recoverable error refreshing %s, automatic refresh will be stopped: %s", certsDescription, err)
return 0, concurrency.ErrNonRecoverable
}

Expand Down Expand Up @@ -97,7 +97,10 @@ func getTimeToRefreshFromRepo(ctx context.Context, getCertsRenewalTime getCertsR
repository serviceCertificatesRepo) (time.Duration, error) {

certificates, getCertsErr := repository.getServiceCertificates(ctx)
if getCertsErr == ErrDifferentCAForDifferentServiceTypes || getCertsErr == ErrMissingSecretData {
if errors.Is(getCertsErr, ErrUnexpectedSecretsOwner) {
return 0, getCertsErr
}
if errors.Is(getCertsErr, ErrDifferentCAForDifferentServiceTypes) || errors.Is(getCertsErr, ErrMissingSecretData) {
log.Errorf("local scanner certificates are in an inconsistent state, "+
"will refresh certificates immediately: %s", getCertsErr)
return 0, nil
Expand Down
10 changes: 6 additions & 4 deletions sensor/kubernetes/localscanner/cert_refresher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"testing"
"time"

"github.com/hashicorp/go-multierror"
"github.com/pkg/errors"
"github.com/stackrox/rox/generated/internalapi/central"
"github.com/stackrox/rox/generated/storage"
Expand Down Expand Up @@ -110,8 +111,8 @@ func (s *certRefresherSuite) TestRefreshCertificatesGetCertsInconsistentImmediat
testCases := map[string]struct {
recoverableErr error
}{
"refresh immediately on ErrDifferentCAForDifferentServiceTypes": {recoverableErr: ErrDifferentCAForDifferentServiceTypes},
"refresh immediately on ErrMissingSecretData": {recoverableErr: ErrMissingSecretData},
"refresh immediately on ErrDifferentCAForDifferentServiceTypes": {recoverableErr: errors.Wrap(ErrDifferentCAForDifferentServiceTypes, "wrap error")},
"refresh immediately on ErrMissingSecretData": {recoverableErr: errors.Wrap(ErrMissingSecretData, "wrap error")},
"refresh immediately on missing secrets": {recoverableErr: k8sErrors.NewNotFound(schema.GroupResource{Group: "Core", Resource: "Secret"}, "foo")},
}
for tcName, tc := range testCases {
Expand All @@ -132,9 +133,10 @@ func (s *certRefresherSuite) TestRefreshCertificatesGetCertsInconsistentImmediat
}
}

func (s *certRefresherSuite) TestRefreshCertificatesGetCertsUnexpectedOwnerFailure() {
func (s *certRefresherSuite) TestRefreshCertificatesGetCertsUnexpectedOwnerHighestPriorityFailure() {
getErr := multierror.Append(nil, ErrUnexpectedSecretsOwner, ErrDifferentCAForDifferentServiceTypes, ErrMissingSecretData)
s.dependenciesMock.On("getServiceCertificates", mock.Anything).Once().Return(
(*storage.TypedServiceCertificateSet)(nil), concurrency.ErrNonRecoverable)
(*storage.TypedServiceCertificateSet)(nil), getErr)

_, err := s.refreshCertificates()

Expand Down
14 changes: 11 additions & 3 deletions sensor/kubernetes/localscanner/certificate_expiration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,23 @@ func (s *getSecretRenewalTimeSuite) TestGetSecretsCertRenewalTime() {
s.LessOrEqual(certDuration, afterOffset/2)
}

func issueCertificatePEM(issueOption mtls.IssueCertOption) ([]byte, error) {
func issueCertificate(serviceType storage.ServiceType, issueOption mtls.IssueCertOption) (*mtls.IssuedCert, error) {
ca, err := mtls.CAForSigning()
if err != nil {
return nil, err
}
subject := mtls.NewSubject("clusterId", storage.ServiceType_SCANNER_SERVICE)
subject := mtls.NewSubject("clusterId", serviceType)
cert, err := ca.IssueCertForSubject(subject, issueOption)
if err != nil {
return nil, err
}
return cert.CertPEM, err
return cert, err
}

func issueCertificatePEM(issueOption mtls.IssueCertOption) ([]byte, error) {
cert, err := issueCertificate(storage.ServiceType_SCANNER_SERVICE, issueOption)
if err != nil {
return nil, err
}
return cert.CertPEM, nil
}
9 changes: 0 additions & 9 deletions sensor/kubernetes/localscanner/certificate_requester.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/pkg/errors"
"github.com/stackrox/rox/generated/internalapi/central"
"github.com/stackrox/rox/pkg/concurrency"
"github.com/stackrox/rox/pkg/logging"
"github.com/stackrox/rox/pkg/sync"
"github.com/stackrox/rox/pkg/uuid"
)
Expand All @@ -15,17 +14,9 @@ var (
// ErrCertificateRequesterStopped is returned by RequestCertificates when the certificate
// requester is not initialized.
ErrCertificateRequesterStopped = errors.New("stopped")
log = logging.LoggerForModule()
_ CertificateRequester = (*certificateRequesterImpl)(nil)
)

// CertificateRequester requests a new set of local scanner certificates from central.
type CertificateRequester interface {
Start()
Stop()
RequestCertificates(ctx context.Context) (*central.IssueLocalScannerCertsResponse, error)
}

// NewCertificateRequester creates a new certificate requester that communicates through
// the specified channels and initializes a new request ID for reach request.
// To use it call Start, and then make requests with RequestCertificates, concurrent requests are supported.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type serviceCertSecretSpec struct {
// newServiceCertificatesRepo creates a new serviceCertificatesRepoSecretsImpl that persists certificates for
// scanner and scanner DB in k8s secrets that are expected to have ownerReference as the only owner reference.
func newServiceCertificatesRepo(ownerReference metav1.OwnerReference, namespace string,
secretsClient corev1.SecretInterface) *serviceCertificatesRepoSecretsImpl {
secretsClient corev1.SecretInterface) serviceCertificatesRepo {

return &serviceCertificatesRepoSecretsImpl{
secrets: map[storage.ServiceType]serviceCertSecretSpec{
Expand Down
Loading