Skip to content
This repository has been archived by the owner on Dec 21, 2023. It is now read-only.

fix(secret-service): changed too big key or name status (#5479) #5631

Merged
merged 4 commits into from
Oct 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 5 additions & 1 deletion secret-service/pkg/backend/secretbackend_k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"

"github.com/keptn/keptn/secret-service/pkg/common"
"github.com/keptn/keptn/secret-service/pkg/model"
"github.com/keptn/keptn/secret-service/pkg/repository"
Expand All @@ -15,13 +14,15 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"strings"
)

const SecretBackendTypeK8s = "kubernetes"
const SecretServiceName = "keptn-secret-service"

var ErrSecretAlreadyExists = errors.New("secret already exists")
var ErrSecretNotFound = errors.New("secret not found")
var ErrTooBigKeySize = errors.New("name and key values must be no more than 253 characters")

type K8sSecretBackend struct {
KubeAPI kubernetes.Interface
Expand Down Expand Up @@ -59,6 +60,9 @@ func (k K8sSecretBackend) CreateSecret(secret model.Secret) error {
_, err = k.KubeAPI.CoreV1().Secrets(namespace).Create(context.TODO(), k.createK8sSecretObj(secret, namespace), metav1.CreateOptions{})
if err != nil {
log.Errorf("Unable to create secret %s with scope %s: %s", secret.Name, secret.Scope, err)
if statusError, isStatus := err.(*k8serr.StatusError); isStatus && statusError.Status().Reason == metav1.StatusReasonInvalid && strings.Contains(statusError.Status().Message, "must be no more than 253 characters") {
return ErrTooBigKeySize
}
if statusError, isStatus := err.(*k8serr.StatusError); isStatus && statusError.Status().Reason == metav1.StatusReasonAlreadyExists {
return ErrSecretAlreadyExists
}
Expand Down
27 changes: 27 additions & 0 deletions secret-service/pkg/backend/secretbackend_k8s_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ import (
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
k8serr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field"
k8sfake "k8s.io/client-go/kubernetes/fake"
k8stesting "k8s.io/client-go/testing"
"testing"
Expand Down Expand Up @@ -84,6 +87,30 @@ func TestCreateSecrets(t *testing.T) {
assert.Equal(t, []string{"my-secret", "my-secret-2"}, k8sRole2.Rules[0].ResourceNames)
}

func TestCreateSecrets_TooLongName(t *testing.T) {
kubernetes := k8sfake.NewSimpleClientset()
scopesRepository := &fake.ScopesRepositoryMock{}
scopesRepository.ReadFunc = func() (model.Scopes, error) { return createTestScopes(), nil }

backend := K8sSecretBackend{
KubeAPI: kubernetes,
KeptnNamespaceProvider: FakeNamespaceProvider(),
ScopesRepository: scopesRepository,
}

secret := createTestSecret("my-verylongname", "my-scope")
kubernetes.Fake.PrependReactor("create", "secrets", func(action k8stesting.Action) (handled bool, ret runtime.Object, err error) {

var errs = field.ErrorList{field.Invalid(nil, nil, " must be no more than 253 characters")}
return true, nil, k8serr.NewInvalid(schema.GroupKind{}, "secret", errs)
})

err := backend.CreateSecret(secret)

assert.NotNil(t, err)
assert.Equal(t, ErrTooBigKeySize, err)
}

func TestCreateSecret_FetchingScopesFails(t *testing.T) {
kubernetes := k8sfake.NewSimpleClientset()
scopesRepository := &fake.ScopesRepositoryMock{}
Expand Down
11 changes: 8 additions & 3 deletions secret-service/pkg/handler/secrethandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"net/http"
)

var ErrCreation = "Unable to create secret"

type ISecretHandler interface {
CreateSecret(c *gin.Context)
UpdateSecret(c *gin.Context)
Expand Down Expand Up @@ -37,7 +39,6 @@ type SecretHandler struct {
// @Failure 500 {object} model.Error
// @Router /secret [post]
func (s SecretHandler) CreateSecret(c *gin.Context) {

secret := model.Secret{}
if err := c.ShouldBindJSON(&secret); err != nil {
SetBadRequestErrorResponse(err, c, "Invalid request format")
Expand All @@ -51,10 +52,14 @@ func (s SecretHandler) CreateSecret(c *gin.Context) {
err := s.SecretBackend.CreateSecret(secret)
if err != nil {
if err == backend.ErrSecretAlreadyExists {
SetConflictErrorResponse(err, c, "Unable to create secret")
SetConflictErrorResponse(err, c, ErrCreation)
return
}
if err == backend.ErrTooBigKeySize {
SetBadRequestErrorResponse(err, c, ErrCreation)
return
}
SetInternalServerErrorResponse(err, c, "Unable to create secret")
SetInternalServerErrorResponse(err, c, ErrCreation)
return
}

Expand Down
10 changes: 10 additions & 0 deletions secret-service/pkg/handler/secrethandler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ func TestHandler_CreateSecret(t *testing.T) {
request: httptest.NewRequest("POST", "/secret", bytes.NewBuffer([]byte(`{"name":"my-secret","scope":"my-scope","data":{"username":"keptn"}}`))),
expectedHTTPStatus: http.StatusInternalServerError,
},
{
name: "POST Create Secret - too long name",
fields: fields{
Backend: &fake.SecretBackendMock{
CreateSecretFunc: func(secret model.Secret) error { return backend.ErrTooBigKeySize },
},
},
request: httptest.NewRequest("POST", "/secret", bytes.NewBuffer([]byte(`{"verylongname":"my-secret","scope":"my-scope","data":{"username":"keptn"}}`))),
expectedHTTPStatus: http.StatusBadRequest,
},
{
name: "POST Create Secret - Input INVALID",
fields: fields{
Expand Down