From 9681d644278d3bd9466baa28bb5b47f4a7c3f3e9 Mon Sep 17 00:00:00 2001 From: changhyuni Date: Mon, 22 Apr 2024 22:29:19 +0900 Subject: [PATCH 01/14] modify maxitmes securitygroups --- apis/vpcresources/v1beta1/securitygrouppolicy_types.go | 2 +- .../crd/bases/vpcresources.k8s.aws_securitygrouppolicies.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apis/vpcresources/v1beta1/securitygrouppolicy_types.go b/apis/vpcresources/v1beta1/securitygrouppolicy_types.go index b929dcf5..1abfba86 100644 --- a/apis/vpcresources/v1beta1/securitygrouppolicy_types.go +++ b/apis/vpcresources/v1beta1/securitygrouppolicy_types.go @@ -30,7 +30,7 @@ type SecurityGroupPolicySpec struct { type GroupIds struct { // Groups is the list of EC2 Security Groups Ids that need to be applied to the ENI of a Pod. // +kubebuilder:validation:MinItems=1 - // +kubebuilder:validation:MaxItems=5 + // +kubebuilder:validation:MaxItems=16 Groups []string `json:"groupIds,omitempty"` } diff --git a/config/crd/bases/vpcresources.k8s.aws_securitygrouppolicies.yaml b/config/crd/bases/vpcresources.k8s.aws_securitygrouppolicies.yaml index 64d4aac0..15d6b905 100644 --- a/config/crd/bases/vpcresources.k8s.aws_securitygrouppolicies.yaml +++ b/config/crd/bases/vpcresources.k8s.aws_securitygrouppolicies.yaml @@ -99,7 +99,7 @@ spec: need to be applied to the ENI of a Pod. items: type: string - maxItems: 5 + maxItems: 16 minItems: 1 type: array type: object From cfcbfdc0bdd9bbc33de417c6141dc9fe058665ae Mon Sep 17 00:00:00 2001 From: changhyuni Date: Mon, 22 Apr 2024 22:59:30 +0900 Subject: [PATCH 02/14] update readmemd --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a1d19d30..f1f2c094 100644 --- a/README.md +++ b/README.md @@ -18,11 +18,8 @@ ENI Trunking is a private feature even though the APIs are publicly accessible u Please follow the [guide](https://docs.aws.amazon.com/eks/latest/userguide/security-groups-for-pods.html) for enabling Security Group for Pods on your EKS Cluster. -Note: The SecurityGroupPolicy CRD only supports up to 5 security groups per custom resource. If you need more than 5 security groups for a pod, please consider to use more than one custom resources. For example, you can have two custom resources to associate up to 10 security groups to a pod. Please be aware when you are doing so: - -1, you need to request increasing the limit since the default limit is 5 security groups per interface and there is a hard limit of 16 currently. - -2, currently Fargate only allows up to 5 security groups. If you are using Fargate, you can only use up to 5 security groups per pod. +Note: The SecurityGroupPolicy CRD only supports up to 16 security groups per custom resource. +1. currently Fargate only allows up to 5 security groups. If you are using Fargate, you can only use up to 5 security groups per pod. ## Windows IPv4 Address Management From 22ec50153d13180ab070a824c16b596e8e436661 Mon Sep 17 00:00:00 2001 From: changhyuni Date: Mon, 22 Apr 2024 23:02:35 +0900 Subject: [PATCH 03/14] update readmemd --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index f1f2c094..4efdc071 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,7 @@ ENI Trunking is a private feature even though the APIs are publicly accessible u Please follow the [guide](https://docs.aws.amazon.com/eks/latest/userguide/security-groups-for-pods.html) for enabling Security Group for Pods on your EKS Cluster. -Note: The SecurityGroupPolicy CRD only supports up to 16 security groups per custom resource. -1. currently Fargate only allows up to 5 security groups. If you are using Fargate, you can only use up to 5 security groups per pod. +Note: The SecurityGroupPolicy CRD only supports up to 16 security groups per custom resource. currently Fargate only allows up to 5 security groups. If you are using Fargate, you can only use up to 5 security groups per pod. ## Windows IPv4 Address Management From f3a588ef4b27d82ddb7eb0a9b89a98b51dd3db3a Mon Sep 17 00:00:00 2001 From: changhyuni Date: Tue, 14 May 2024 18:58:55 +0900 Subject: [PATCH 04/14] add crd webhook --- go.mod | 14 ++++++ go.sum | 28 ++++++++++++ webhooks/core/crd_validation_webhook.go | 60 +++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 webhooks/core/crd_validation_webhook.go diff --git a/go.mod b/go.mod index 1c748137..4af6557e 100644 --- a/go.mod +++ b/go.mod @@ -26,6 +26,20 @@ require ( ) require ( + github.com/aws/aws-sdk-go-v2 v1.26.1 // indirect + github.com/aws/aws-sdk-go-v2/config v1.27.13 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.13 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 // indirect + github.com/aws/aws-sdk-go-v2/service/servicequotas v1.21.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.20.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.28.7 // indirect + github.com/aws/smithy-go v1.20.2 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect diff --git a/go.sum b/go.sum index f15bc12f..6e31d8df 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,34 @@ github.com/aws/amazon-vpc-cni-k8s v1.17.1 h1:pF+AmlGbgK8/e58LbtOsLUzDy2hqI8Ug/D8 github.com/aws/amazon-vpc-cni-k8s v1.17.1/go.mod h1:fNfKsEUNrAj+046SGML0UQWLcsF7hAsKRqnvwIcflvw= github.com/aws/aws-sdk-go v1.51.12 h1:DvuhIHZXwnjaR1/Gu19gUe1EGPw4J0qSJw4Qs/5PA8g= github.com/aws/aws-sdk-go v1.51.12/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA= +github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= +github.com/aws/aws-sdk-go-v2/config v1.27.13 h1:WbKW8hOzrWoOA/+35S5okqO/2Ap8hkkFUzoW8Hzq24A= +github.com/aws/aws-sdk-go-v2/config v1.27.13/go.mod h1:XLiyiTMnguytjRER7u5RIkhIqS8Nyz41SwAWb4xEjxs= +github.com/aws/aws-sdk-go-v2/credentials v1.17.13 h1:XDCJDzk/u5cN7Aple7D/MiAhx1Rjo/0nueJ0La8mRuE= +github.com/aws/aws-sdk-go-v2/credentials v1.17.13/go.mod h1:FMNcjQrmuBYvOTZDtOLCIu0esmxjF7RuA/89iSXWzQI= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk= +github.com/aws/aws-sdk-go-v2/service/servicequotas v1.21.5 h1:VBOOV74qxUZYEZ9nv+G/ytXnVG5irZ/+HKB5mC8keuo= +github.com/aws/aws-sdk-go-v2/service/servicequotas v1.21.5/go.mod h1:plXue/Zg49kU3uU6WwfCWgRR5SRINNiJf03Y/UhYOhU= +github.com/aws/aws-sdk-go-v2/service/sso v1.20.6 h1:o5cTaeunSpfXiLTIBx5xo2enQmiChtu1IBbzXnfU9Hs= +github.com/aws/aws-sdk-go-v2/service/sso v1.20.6/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.0 h1:Qe0r0lVURDDeBQJ4yP+BOrJkvkiCo/3FH/t+wY11dmw= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.0/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak= +github.com/aws/aws-sdk-go-v2/service/sts v1.28.7 h1:et3Ta53gotFR4ERLXXHIHl/Uuk1qYpP5uU7cvNql8ns= +github.com/aws/aws-sdk-go-v2/service/sts v1.28.7/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw= +github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= +github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= diff --git a/webhooks/core/crd_validation_webhook.go b/webhooks/core/crd_validation_webhook.go new file mode 100644 index 00000000..4c709f79 --- /dev/null +++ b/webhooks/core/crd_validation_webhook.go @@ -0,0 +1,60 @@ +package core + +import ( + "context" + "fmt" + "net/http" + + v1beta1 "github.com/aws/amazon-vpc-resource-controller-k8s/apis/vpcresources/v1beta1" + + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/servicequotas" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// SecurityGroupQuotaValidator handles validation of SecurityGroupPolicies +type SecurityGroupQuotaValidator struct { + Client *servicequotas.Client + Decoder *admission.Decoder + QuotaCode string + ServiceCode string +} + +func NewSecurityGroupQuotaValidator() (*SecurityGroupQuotaValidator, error) { + cfg, err := config.LoadDefaultConfig(context.TODO()) + if err != nil { + return nil, fmt.Errorf("unable to load SDK config, %w", err) + } + svc := servicequotas.NewFromConfig(cfg) + return &SecurityGroupQuotaValidator{ + Client: svc, + QuotaCode: "L-2AFB9258", // Security groups per network interface QuotaCode + ServiceCode: "vpc", + }, nil +} + +// Handle allows compare the number of vpc servicequots currently to your AWS account with the number of SecurityGroups requested +func (v *SecurityGroupQuotaValidator) Handle(ctx context.Context, req admission.Request) admission.Response { + policy := &v1beta1.SecurityGroupPolicy{} + if err := v.Decoder.Decode(req, policy); err != nil { + return admission.Errored(http.StatusBadRequest, err) + } + + // Get the current quota for security groups + quota, err := v.Client.GetServiceQuota(ctx, &servicequotas.GetServiceQuotaInput{ + QuotaCode: &v.QuotaCode, + ServiceCode: &v.ServiceCode, + }) + if err != nil { + return admission.Errored(http.StatusInternalServerError, fmt.Errorf("failed to fetch service quota: %w", err)) + } + + maxGroups := int(*quota.Quota.Value) + if len(policy.Spec.SecurityGroups.Groups) > maxGroups { + return admission.Denied( + fmt.Sprintf("validation error: number of group IDs %d exceeds quota of %d", len(policy.Spec.SecurityGroups.Groups), maxGroups), + ) + } + + return admission.Allowed("SecurityGroupPolicy validation passed") +} From 03d2f2511781fc55bbd894b9193b45e4f6cca5ef Mon Sep 17 00:00:00 2001 From: june Date: Sun, 2 Jun 2024 04:00:25 +0900 Subject: [PATCH 05/14] Add ec2api servicequtoa and pod webhook --- go.mod | 13 ---- .../pkg/aws/ec2/api/mock_ec2_apihelper.go | 15 +++++ .../pkg/aws/ec2/api/mock_ec2_wrapper.go | 16 +++++ pkg/aws/ec2/api/helper.go | 16 +++++ pkg/aws/ec2/api/helper_test.go | 44 ++++++++++++++ pkg/aws/ec2/api/wrapper.go | 39 ++++++++++++ webhooks/core/crd_validation_webhook.go | 60 ------------------- webhooks/core/pod_webhook.go | 48 ++++++++++++--- webhooks/core/pod_webhook_test.go | 16 +++-- 9 files changed, 182 insertions(+), 85 deletions(-) delete mode 100644 webhooks/core/crd_validation_webhook.go diff --git a/go.mod b/go.mod index 1968df76..f9c0e7c9 100644 --- a/go.mod +++ b/go.mod @@ -26,19 +26,6 @@ require ( ) require ( - github.com/aws/aws-sdk-go-v2 v1.26.1 // indirect - github.com/aws/aws-sdk-go-v2/config v1.27.13 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.13 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 // indirect - github.com/aws/aws-sdk-go-v2/service/servicequotas v1.21.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.20.6 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.28.7 // indirect github.com/aws/smithy-go v1.20.2 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect diff --git a/mocks/amazon-vcp-resource-controller-k8s/pkg/aws/ec2/api/mock_ec2_apihelper.go b/mocks/amazon-vcp-resource-controller-k8s/pkg/aws/ec2/api/mock_ec2_apihelper.go index 6bd94eb3..338fb74d 100644 --- a/mocks/amazon-vcp-resource-controller-k8s/pkg/aws/ec2/api/mock_ec2_apihelper.go +++ b/mocks/amazon-vcp-resource-controller-k8s/pkg/aws/ec2/api/mock_ec2_apihelper.go @@ -310,3 +310,18 @@ func (mr *MockEC2APIHelperMockRecorder) WaitForNetworkInterfaceStatusChange(arg0 mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WaitForNetworkInterfaceStatusChange", reflect.TypeOf((*MockEC2APIHelper)(nil).WaitForNetworkInterfaceStatusChange), arg0, arg1) } + +// GetSecurityGroupQuota mocks base method. +func (m *MockEC2APIHelper) GetSecurityGroupQuota(quotaCode, serviceCode *string) (int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSecurityGroupQuota", quotaCode, serviceCode) + ret0, _ := ret[0].(int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSecurityGroupQuota indicates an expected call of GetSecurityGroupQuota. +func (mr *MockEC2APIHelperMockRecorder) GetSecurityGroupQuota(quotaCode, serviceCode interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSecurityGroupQuota", reflect.TypeOf((*MockEC2APIHelper)(nil).GetSecurityGroupQuota), quotaCode, serviceCode) +} \ No newline at end of file diff --git a/mocks/amazon-vcp-resource-controller-k8s/pkg/aws/ec2/api/mock_ec2_wrapper.go b/mocks/amazon-vcp-resource-controller-k8s/pkg/aws/ec2/api/mock_ec2_wrapper.go index 53515c5d..87c5ea7e 100644 --- a/mocks/amazon-vcp-resource-controller-k8s/pkg/aws/ec2/api/mock_ec2_wrapper.go +++ b/mocks/amazon-vcp-resource-controller-k8s/pkg/aws/ec2/api/mock_ec2_wrapper.go @@ -20,6 +20,7 @@ package mock_api import ( reflect "reflect" + servicequotas "github.com/aws/aws-sdk-go/service/servicequotas" ec2 "github.com/aws/aws-sdk-go/service/ec2" gomock "github.com/golang/mock/gomock" ) @@ -285,3 +286,18 @@ func (mr *MockEC2WrapperMockRecorder) UnassignPrivateIPAddresses(arg0 interface{ mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnassignPrivateIPAddresses", reflect.TypeOf((*MockEC2Wrapper)(nil).UnassignPrivateIPAddresses), arg0) } + +// GetServiceQuota mocks base method. +func (m *MockEC2Wrapper) GetServiceQuota(input *servicequotas.GetServiceQuotaInput) (int, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetServiceQuota", input) + ret0, _ := ret[0].(int) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetServiceQuota indicates an expected call of GetServiceQuota. +func (mr *MockEC2WrapperMockRecorder) GetServiceQuota(input interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceQuota", reflect.TypeOf((*MockEC2Wrapper)(nil).GetServiceQuota), input) +} diff --git a/pkg/aws/ec2/api/helper.go b/pkg/aws/ec2/api/helper.go index 17ff32eb..78c36acb 100644 --- a/pkg/aws/ec2/api/helper.go +++ b/pkg/aws/ec2/api/helper.go @@ -19,6 +19,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/servicequotas" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/util/retry" @@ -94,6 +95,7 @@ type EC2APIHelper interface { AssignIPv4ResourcesAndWaitTillReady(eniID string, resourceType config.ResourceType, count int) ([]string, error) UnassignIPv4Resources(eniID string, resourceType config.ResourceType, resources []string) error DisassociateTrunkInterface(associationID *string) error + GetSecurityGroupQuota(quotaCode, serviceCode *string) (int, error) } // CreateNetworkInterface creates a new network interface @@ -630,3 +632,17 @@ func (h *ec2APIHelper) DisassociateTrunkInterface(associationID *string) error { } return h.ec2Wrapper.DisassociateTrunkInterface(input) } + +func (h *ec2APIHelper) GetSecurityGroupQuota(quotaCode, serviceCode *string) (int, error) { + input := &servicequotas.GetServiceQuotaInput{ + QuotaCode: quotaCode, + ServiceCode: serviceCode, + } + serviceQuotaOutput, err := h.ec2Wrapper.GetServiceQuota(input) + if err != nil { + return 5, fmt.Errorf("failed to retrieve security group quota: %v", err) + } + fmt.Println(serviceQuotaOutput) + + return int(serviceQuotaOutput), nil +} diff --git a/pkg/aws/ec2/api/helper_test.go b/pkg/aws/ec2/api/helper_test.go index b2dd7644..92011859 100644 --- a/pkg/aws/ec2/api/helper_test.go +++ b/pkg/aws/ec2/api/helper_test.go @@ -23,6 +23,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/servicequotas" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/util/wait" @@ -1185,3 +1186,46 @@ func TestEc2APIHelper_GetBranchNetworkInterface(t *testing.T) { assert.NoError(t, err) assert.ElementsMatch(t, []*ec2.NetworkInterface{&networkInterface1, &networkInterface2}, branchInterfaces) } + +// TestEc2APIHelper_GetSecurityGroupQuota tests the GetSecurityGroupQuota function +func TestEc2APIHelper_GetSecurityGroupQuota(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ec2ApiHelper, mockWrapper := getMockWrapper(ctrl) + + quotaCode := "L-1234ABCD" + serviceCode := "ec2" + + getServiceQuotaInput := &servicequotas.GetServiceQuotaInput{ + QuotaCode: "aCode, + ServiceCode: &serviceCode, + } + + mockWrapper.EXPECT().GetServiceQuota(getServiceQuotaInput).Return(5, nil) + + quota, err := ec2ApiHelper.GetSecurityGroupQuota("aCode, &serviceCode) + assert.NoError(t, err) + assert.Equal(t, 5, quota) +} + +// TestEc2APIHelper_GetSecurityGroupQuota_Error tests that error is returned if GetServiceQuota call fails +func TestEc2APIHelper_GetSecurityGroupQuota_Error(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + ec2ApiHelper, mockWrapper := getMockWrapper(ctrl) + + quotaCode := "L-1234ABCD" + serviceCode := "ec2" + + getServiceQuotaInput := &servicequotas.GetServiceQuotaInput{ + QuotaCode: "aCode, + ServiceCode: &serviceCode, + } + + mockWrapper.EXPECT().GetServiceQuota(getServiceQuotaInput).Return(5, mockError) + + _, err := ec2ApiHelper.GetSecurityGroupQuota("aCode, &serviceCode) + assert.Error(t, err) +} diff --git a/pkg/aws/ec2/api/wrapper.go b/pkg/aws/ec2/api/wrapper.go index 97a20f3b..d8531724 100644 --- a/pkg/aws/ec2/api/wrapper.go +++ b/pkg/aws/ec2/api/wrapper.go @@ -31,6 +31,7 @@ import ( "github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/servicequotas" "github.com/aws/aws-sdk-go/service/sts" "github.com/go-logr/logr" "github.com/prometheus/client_golang/prometheus" @@ -61,6 +62,7 @@ type EC2Wrapper interface { ModifyNetworkInterfaceAttribute(input *ec2.ModifyNetworkInterfaceAttributeInput) (*ec2.ModifyNetworkInterfaceAttributeOutput, error) CreateNetworkInterfacePermission(input *ec2.CreateNetworkInterfacePermissionInput) (*ec2.CreateNetworkInterfacePermissionOutput, error) DisassociateTrunkInterface(input *ec2.DisassociateTrunkInterfaceInput) error + GetServiceQuota(input *servicequotas.GetServiceQuotaInput) (int, error) } var ( @@ -358,6 +360,19 @@ var ( }, ) + ec2GetServiceQuotaAPICallCnt = prometheus.NewCounter( + prometheus.CounterOpts{ + Name: "ec2_describe_network_interfaces_pages_api_err_count", + Help: "The number of errors encountered while making call to get service quotas", + }, + ) + ec2GetServiceQuotaAPIErrCnt = prometheus.NewCounter( + prometheus.CounterOpts{ + Name: "ec2_get_service_quota_api_err_count", + Help: "The number of errors encountered while making call to get service quotas", + }, + ) + prometheusRegistered = false ) @@ -403,6 +418,8 @@ func prometheusRegister() { LeakedENIClusterCleanupCnt, ec2DescribeNetworkInterfacesPagesAPICallCnt, ec2DescribeNetworkInterfacesPagesAPIErrCnt, + ec2GetServiceQuotaAPICallCnt, + ec2GetServiceQuotaAPIErrCnt, ) prometheusRegistered = true @@ -413,6 +430,7 @@ type ec2Wrapper struct { log logr.Logger instanceServiceClient *ec2.EC2 userServiceClient *ec2.EC2 + serviceQuotasClient *servicequotas.ServiceQuotas accountID string } @@ -429,6 +447,10 @@ func NewEC2Wrapper(roleARN, clusterName, region string, log logr.Logger) (EC2Wra return nil, err } + // Initialize the service quotas client + serviceQuotasClient := servicequotas.New(instanceSession) + ec2Wrapper.serviceQuotasClient = serviceQuotasClient + // Role ARN is passed, assume the role ARN to make EC2 API Calls if roleARN != "" { // Create the instance service client with low QPS, it will be only used for associate branch to trunk calls @@ -892,3 +914,20 @@ func (e *ec2Wrapper) DisassociateTrunkInterface(input *ec2.DisassociateTrunkInte } return err } + +func (e *ec2Wrapper) GetServiceQuota(input *servicequotas.GetServiceQuotaInput) (int, error) { + start := time.Now() + // Using the service quotas client + output, err := e.serviceQuotasClient.GetServiceQuota(input) + ec2APICallLatencies.WithLabelValues("get_service_quota").Observe(time.Since(start).Seconds() * 1e3) // milliseconds + + // Metric Update + ec2APICallCnt.Inc() + ec2GetServiceQuotaAPICallCnt.Inc() + + if err != nil { + ec2APIErrCnt.Inc() + ec2GetServiceQuotaAPIErrCnt.Inc() + } + return int(*output.Quota.Value), nil +} diff --git a/webhooks/core/crd_validation_webhook.go b/webhooks/core/crd_validation_webhook.go deleted file mode 100644 index 4c709f79..00000000 --- a/webhooks/core/crd_validation_webhook.go +++ /dev/null @@ -1,60 +0,0 @@ -package core - -import ( - "context" - "fmt" - "net/http" - - v1beta1 "github.com/aws/amazon-vpc-resource-controller-k8s/apis/vpcresources/v1beta1" - - "github.com/aws/aws-sdk-go-v2/config" - "github.com/aws/aws-sdk-go-v2/service/servicequotas" - "sigs.k8s.io/controller-runtime/pkg/webhook/admission" -) - -// SecurityGroupQuotaValidator handles validation of SecurityGroupPolicies -type SecurityGroupQuotaValidator struct { - Client *servicequotas.Client - Decoder *admission.Decoder - QuotaCode string - ServiceCode string -} - -func NewSecurityGroupQuotaValidator() (*SecurityGroupQuotaValidator, error) { - cfg, err := config.LoadDefaultConfig(context.TODO()) - if err != nil { - return nil, fmt.Errorf("unable to load SDK config, %w", err) - } - svc := servicequotas.NewFromConfig(cfg) - return &SecurityGroupQuotaValidator{ - Client: svc, - QuotaCode: "L-2AFB9258", // Security groups per network interface QuotaCode - ServiceCode: "vpc", - }, nil -} - -// Handle allows compare the number of vpc servicequots currently to your AWS account with the number of SecurityGroups requested -func (v *SecurityGroupQuotaValidator) Handle(ctx context.Context, req admission.Request) admission.Response { - policy := &v1beta1.SecurityGroupPolicy{} - if err := v.Decoder.Decode(req, policy); err != nil { - return admission.Errored(http.StatusBadRequest, err) - } - - // Get the current quota for security groups - quota, err := v.Client.GetServiceQuota(ctx, &servicequotas.GetServiceQuotaInput{ - QuotaCode: &v.QuotaCode, - ServiceCode: &v.ServiceCode, - }) - if err != nil { - return admission.Errored(http.StatusInternalServerError, fmt.Errorf("failed to fetch service quota: %w", err)) - } - - maxGroups := int(*quota.Quota.Value) - if len(policy.Spec.SecurityGroups.Groups) > maxGroups { - return admission.Denied( - fmt.Sprintf("validation error: number of group IDs %d exceeds quota of %d", len(policy.Spec.SecurityGroups.Groups), maxGroups), - ) - } - - return admission.Allowed("SecurityGroupPolicy validation passed") -} diff --git a/webhooks/core/pod_webhook.go b/webhooks/core/pod_webhook.go index b6fa0019..dedb47f8 100644 --- a/webhooks/core/pod_webhook.go +++ b/webhooks/core/pod_webhook.go @@ -16,6 +16,7 @@ package core import ( "context" "encoding/json" + "fmt" "net/http" "strings" @@ -25,8 +26,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + "github.com/aws/amazon-vpc-resource-controller-k8s/pkg/aws/ec2/api" "github.com/aws/amazon-vpc-resource-controller-k8s/pkg/condition" "github.com/aws/amazon-vpc-resource-controller-k8s/pkg/config" + rcHealthz "github.com/aws/amazon-vpc-resource-controller-k8s/pkg/healthz" "github.com/aws/amazon-vpc-resource-controller-k8s/pkg/utils" ) @@ -41,10 +44,11 @@ const ( // PodResourceInjector injects resources into Pods type PodMutationWebHook struct { - decoder *admission.Decoder - SGPAPI utils.SecurityGroupForPodsAPI - Log logr.Logger - Condition condition.Conditions + decoder *admission.Decoder + SGPAPI utils.SecurityGroupForPodsAPI + Log logr.Logger + Condition condition.Conditions + ec2ApiHelper api.EC2APIHelper } func NewPodMutationWebHook( @@ -53,12 +57,14 @@ func NewPodMutationWebHook( condition condition.Conditions, d *admission.Decoder, healthzHandler *rcHealthz.HealthzHandler, + ec2ApiHelper api.EC2APIHelper, ) *PodMutationWebHook { podWebhook := &PodMutationWebHook{ - SGPAPI: sgpAPI, - Log: log, - Condition: condition, - decoder: d, + SGPAPI: sgpAPI, + Log: log, + Condition: condition, + decoder: d, + ec2ApiHelper: ec2ApiHelper, } // add health check on subpath for pod mutation webhook healthzHandler.AddControllersHealthCheckers( @@ -149,6 +155,13 @@ func (i *PodMutationWebHook) HandleFargatePod(req admission.Request, pod *corev1 response = admission.Allowed("Fargate pod not matching any SGP") } default: + // If more than 5 SGs match for the Pod, deny the request + // Fargate only allows up to 5 security groups. If you are using Fargate, you can only use up to 5 security groups per pod + // if len(sgList) > 5 { + // log.Info("Denying request due to too many matching security groups", + // "Security Groups", sgList) + // return admission.Denied("Too many matching security groups, rejecting event") + // } // If more than 1 SG match for the Pod then add all matching SG to the Annotation pod.Annotations[FargatePodSGAnnotationKey] = strings.Join(sgList, ",") log.Info("annotating Fargate pod with matching security groups", @@ -184,6 +197,8 @@ func (i *PodMutationWebHook) HandleLinuxPod(req admission.Request, pod *corev1.P log logr.Logger) (response admission.Response) { sgList, err := i.SGPAPI.GetMatchingSecurityGroupForPods(pod) + fmt.Println(err, "에러입니다") + if err != nil { i.Log.Error(err, "failed to get matching SGP for Pods", "namespace", pod.Namespace, "name", pod.Name) @@ -193,6 +208,23 @@ func (i *PodMutationWebHook) HandleLinuxPod(req admission.Request, pod *corev1.P return admission.Allowed("Pod didn't match any SGP") } + quotaCode := "L-2AFB9258" // Security groups per network interface QuotaCode + serviceCode := "vpc" + + securityGroupQuota, err := i.ec2ApiHelper.GetSecurityGroupQuota("aCode, &serviceCode) + if err != nil { + i.Log.Error(err, "failed to get security group quota", + "namespace", pod.Namespace, "name", pod.Name) + return admission.Denied("Failed to get security group quota, rejecting event") + } + + // Verify that the number of securitygroups matches sevicequtoa + if len(sgList) > securityGroupQuota { + log.Info("Denied the security groups to match quota", + "Original Security Groups", sgList, "Quota", securityGroupQuota) + return admission.Denied("Exceed security group quota, rejecting event") + } + log.Info("injecting resource to the first container of the pod", "resource name", config.ResourceNamePodENI, "resource count", DefaultResourceLimit) diff --git a/webhooks/core/pod_webhook_test.go b/webhooks/core/pod_webhook_test.go index cd934b87..0f709862 100644 --- a/webhooks/core/pod_webhook_test.go +++ b/webhooks/core/pod_webhook_test.go @@ -20,6 +20,7 @@ import ( "strings" "testing" + mock_api "github.com/aws/amazon-vpc-resource-controller-k8s/mocks/amazon-vcp-resource-controller-k8s/pkg/aws/ec2/api" mock_condition "github.com/aws/amazon-vpc-resource-controller-k8s/mocks/amazon-vcp-resource-controller-k8s/pkg/condition" mock_utils "github.com/aws/amazon-vpc-resource-controller-k8s/mocks/amazon-vcp-resource-controller-k8s/pkg/utils" "github.com/aws/amazon-vpc-resource-controller-k8s/pkg/config" @@ -48,6 +49,7 @@ var ( type Mock struct { SGPMock *mock_utils.MockSecurityGroupForPodsAPI ConditionMock *mock_condition.MockConditions + EC2Mock *mock_api.MockEC2APIHelper } func TestPodMutationWebHook_Handle(t *testing.T) { @@ -159,6 +161,7 @@ func TestPodMutationWebHook_Handle(t *testing.T) { }, mockInvocation: func(mock Mock) { mock.SGPMock.EXPECT().GetMatchingSecurityGroupForPods(gomock.AssignableToTypeOf(sgpPod)).Return(sgList, nil) + mock.EC2Mock.EXPECT().GetSecurityGroupQuota(gomock.Any(), gomock.Any()).Return(5, nil) }, want: admission.Response{ @@ -192,6 +195,7 @@ func TestPodMutationWebHook_Handle(t *testing.T) { }, mockInvocation: func(mock Mock) { mock.SGPMock.EXPECT().GetMatchingSecurityGroupForPods(gomock.AssignableToTypeOf(sgpPod)).Return(sgList, nil) + mock.EC2Mock.EXPECT().GetSecurityGroupQuota(gomock.Any(), gomock.Any()).Return(5, nil) }, want: admission.Response{ @@ -225,6 +229,7 @@ func TestPodMutationWebHook_Handle(t *testing.T) { }, mockInvocation: func(mock Mock) { mock.SGPMock.EXPECT().GetMatchingSecurityGroupForPods(gomock.AssignableToTypeOf(sgpPod)).Return([]string{}, nil) + mock.EC2Mock.EXPECT().GetSecurityGroupQuota(gomock.Any(), gomock.Any()).Return(5, nil) }, want: admission.Response{ @@ -245,6 +250,7 @@ func TestPodMutationWebHook_Handle(t *testing.T) { }, mockInvocation: func(mock Mock) { mock.SGPMock.EXPECT().GetMatchingSecurityGroupForPods(gomock.AssignableToTypeOf(sgpPod)).Return(nil, mockErr) + mock.EC2Mock.EXPECT().GetSecurityGroupQuota(gomock.Any(), gomock.Any()).Return(5, nil) }, want: admission.Response{ @@ -517,13 +523,15 @@ func TestPodMutationWebHook_Handle(t *testing.T) { ctx := context.TODO() mock := Mock{ SGPMock: mock_utils.NewMockSecurityGroupForPodsAPI(ctrl), + EC2Mock: mock_api.NewMockEC2APIHelper(ctrl), ConditionMock: mock_condition.NewMockConditions(ctrl), } h := &PodMutationWebHook{ - decoder: decoder, - Log: zap.New(), - SGPAPI: mock.SGPMock, - Condition: mock.ConditionMock, + decoder: decoder, + Log: zap.New(), + SGPAPI: mock.SGPMock, + ec2ApiHelper: mock.EC2Mock, + Condition: mock.ConditionMock, } if tt.mockInvocation != nil { From 52bb0d7b9eafd9e9a765a6270d9c140e02022864 Mon Sep 17 00:00:00 2001 From: june Date: Sun, 2 Jun 2024 04:02:49 +0900 Subject: [PATCH 06/14] Remove unused package --- go.mod | 1 - go.sum | 30 ------------------------------ 2 files changed, 31 deletions(-) diff --git a/go.mod b/go.mod index f9c0e7c9..13b4e1a5 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,6 @@ require ( ) require ( - github.com/aws/smithy-go v1.20.2 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/gorilla/websocket v1.5.0 // indirect diff --git a/go.sum b/go.sum index 8fb0005a..d7fcb41c 100644 --- a/go.sum +++ b/go.sum @@ -1,37 +1,7 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/aws/amazon-vpc-cni-k8s v1.17.1 h1:pF+AmlGbgK8/e58LbtOsLUzDy2hqI8Ug/D8Xxx7+Sis= -github.com/aws/amazon-vpc-cni-k8s v1.17.1/go.mod h1:fNfKsEUNrAj+046SGML0UQWLcsF7hAsKRqnvwIcflvw= github.com/aws/aws-sdk-go v1.51.12 h1:DvuhIHZXwnjaR1/Gu19gUe1EGPw4J0qSJw4Qs/5PA8g= github.com/aws/aws-sdk-go v1.51.12/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= -github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA= -github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= -github.com/aws/aws-sdk-go-v2/config v1.27.13 h1:WbKW8hOzrWoOA/+35S5okqO/2Ap8hkkFUzoW8Hzq24A= -github.com/aws/aws-sdk-go-v2/config v1.27.13/go.mod h1:XLiyiTMnguytjRER7u5RIkhIqS8Nyz41SwAWb4xEjxs= -github.com/aws/aws-sdk-go-v2/credentials v1.17.13 h1:XDCJDzk/u5cN7Aple7D/MiAhx1Rjo/0nueJ0La8mRuE= -github.com/aws/aws-sdk-go-v2/credentials v1.17.13/go.mod h1:FMNcjQrmuBYvOTZDtOLCIu0esmxjF7RuA/89iSXWzQI= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk= -github.com/aws/aws-sdk-go-v2/service/servicequotas v1.21.5 h1:VBOOV74qxUZYEZ9nv+G/ytXnVG5irZ/+HKB5mC8keuo= -github.com/aws/aws-sdk-go-v2/service/servicequotas v1.21.5/go.mod h1:plXue/Zg49kU3uU6WwfCWgRR5SRINNiJf03Y/UhYOhU= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.6 h1:o5cTaeunSpfXiLTIBx5xo2enQmiChtu1IBbzXnfU9Hs= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.6/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.0 h1:Qe0r0lVURDDeBQJ4yP+BOrJkvkiCo/3FH/t+wY11dmw= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.0/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.7 h1:et3Ta53gotFR4ERLXXHIHl/Uuk1qYpP5uU7cvNql8ns= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.7/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw= -github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= -github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/aws/amazon-vpc-cni-k8s v1.18.1 h1:u/OeBgnUUX6f3PCEOpA4dbG0+iZ71CnY6tEljjrl3iw= github.com/aws/amazon-vpc-cni-k8s v1.18.1/go.mod h1:m/J5GsxF0Th2iQTOE3ww4W9LFvwdC0tGyA9dIL4h6iQ= github.com/aws/aws-sdk-go v1.51.32 h1:A6mPui7QP4mwmovyzgtdedbRbNur1Iu0/El7hBWNHms= From 0f95e2acc4c7bc19f0985ffcf3d41021f5644bc6 Mon Sep 17 00:00:00 2001 From: june Date: Sun, 2 Jun 2024 04:03:23 +0900 Subject: [PATCH 07/14] Remove unused package --- go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.sum b/go.sum index d7fcb41c..f8b72bdc 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,6 @@ github.com/aws/aws-sdk-go v1.51.12 h1:DvuhIHZXwnjaR1/Gu19gUe1EGPw4J0qSJw4Qs/5PA8 github.com/aws/aws-sdk-go v1.51.12/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/amazon-vpc-cni-k8s v1.18.1 h1:u/OeBgnUUX6f3PCEOpA4dbG0+iZ71CnY6tEljjrl3iw= github.com/aws/amazon-vpc-cni-k8s v1.18.1/go.mod h1:m/J5GsxF0Th2iQTOE3ww4W9LFvwdC0tGyA9dIL4h6iQ= -github.com/aws/aws-sdk-go v1.51.32 h1:A6mPui7QP4mwmovyzgtdedbRbNur1Iu0/El7hBWNHms= -github.com/aws/aws-sdk-go v1.51.32/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= From f1b80417e1050e5d2d20967fcd38e96bd5ad129c Mon Sep 17 00:00:00 2001 From: june Date: Sun, 2 Jun 2024 04:04:09 +0900 Subject: [PATCH 08/14] modify package version --- go.sum | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go.sum b/go.sum index f8b72bdc..da306dc7 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/aws/aws-sdk-go v1.51.12 h1:DvuhIHZXwnjaR1/Gu19gUe1EGPw4J0qSJw4Qs/5PA8g= -github.com/aws/aws-sdk-go v1.51.12/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go v1.51.32 h1:A6mPui7QP4mwmovyzgtdedbRbNur1Iu0/El7hBWNHms= +github.com/aws/aws-sdk-go v1.51.32/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/amazon-vpc-cni-k8s v1.18.1 h1:u/OeBgnUUX6f3PCEOpA4dbG0+iZ71CnY6tEljjrl3iw= github.com/aws/amazon-vpc-cni-k8s v1.18.1/go.mod h1:m/J5GsxF0Th2iQTOE3ww4W9LFvwdC0tGyA9dIL4h6iQ= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= From 400e6a9c14ee5c09295f006198c686910ea08980 Mon Sep 17 00:00:00 2001 From: june Date: Sun, 2 Jun 2024 04:05:02 +0900 Subject: [PATCH 09/14] fix go.sum --- go.sum | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go.sum b/go.sum index da306dc7..9215561b 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,9 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/aws/aws-sdk-go v1.51.32 h1:A6mPui7QP4mwmovyzgtdedbRbNur1Iu0/El7hBWNHms= -github.com/aws/aws-sdk-go v1.51.32/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/amazon-vpc-cni-k8s v1.18.1 h1:u/OeBgnUUX6f3PCEOpA4dbG0+iZ71CnY6tEljjrl3iw= github.com/aws/amazon-vpc-cni-k8s v1.18.1/go.mod h1:m/J5GsxF0Th2iQTOE3ww4W9LFvwdC0tGyA9dIL4h6iQ= +github.com/aws/aws-sdk-go v1.51.32 h1:A6mPui7QP4mwmovyzgtdedbRbNur1Iu0/El7hBWNHms= +github.com/aws/aws-sdk-go v1.51.32/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= From f1faaa602fe350ae03d9285a2d7d20faff20d995 Mon Sep 17 00:00:00 2001 From: june Date: Sun, 2 Jun 2024 04:06:02 +0900 Subject: [PATCH 10/14] remove fmt --- pkg/aws/ec2/api/helper.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/aws/ec2/api/helper.go b/pkg/aws/ec2/api/helper.go index 78c36acb..91bd5d5f 100644 --- a/pkg/aws/ec2/api/helper.go +++ b/pkg/aws/ec2/api/helper.go @@ -642,7 +642,5 @@ func (h *ec2APIHelper) GetSecurityGroupQuota(quotaCode, serviceCode *string) (in if err != nil { return 5, fmt.Errorf("failed to retrieve security group quota: %v", err) } - fmt.Println(serviceQuotaOutput) - return int(serviceQuotaOutput), nil } From 839856cb1716d5362b1badfbeef7c286e1e3306a Mon Sep 17 00:00:00 2001 From: june Date: Sun, 2 Jun 2024 04:09:18 +0900 Subject: [PATCH 11/14] modify describe --- pkg/aws/ec2/api/wrapper.go | 4 ++-- webhooks/core/pod_webhook.go | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pkg/aws/ec2/api/wrapper.go b/pkg/aws/ec2/api/wrapper.go index d8531724..f3018223 100644 --- a/pkg/aws/ec2/api/wrapper.go +++ b/pkg/aws/ec2/api/wrapper.go @@ -363,13 +363,13 @@ var ( ec2GetServiceQuotaAPICallCnt = prometheus.NewCounter( prometheus.CounterOpts{ Name: "ec2_describe_network_interfaces_pages_api_err_count", - Help: "The number of errors encountered while making call to get service quotas", + Help: "The number of calls made to get service quotas (paginated)", }, ) ec2GetServiceQuotaAPIErrCnt = prometheus.NewCounter( prometheus.CounterOpts{ Name: "ec2_get_service_quota_api_err_count", - Help: "The number of errors encountered while making call to get service quotas", + Help: "The number of errors encountered while making call to get service quotas (paginated)", }, ) diff --git a/webhooks/core/pod_webhook.go b/webhooks/core/pod_webhook.go index dedb47f8..d55e8aab 100644 --- a/webhooks/core/pod_webhook.go +++ b/webhooks/core/pod_webhook.go @@ -16,7 +16,6 @@ package core import ( "context" "encoding/json" - "fmt" "net/http" "strings" @@ -195,15 +194,13 @@ func (i *PodMutationWebHook) HandleWindowsPod(req admission.Request, pod *corev1 // matches any SGP func (i *PodMutationWebHook) HandleLinuxPod(req admission.Request, pod *corev1.Pod, log logr.Logger) (response admission.Response) { - sgList, err := i.SGPAPI.GetMatchingSecurityGroupForPods(pod) - fmt.Println(err, "에러입니다") - if err != nil { i.Log.Error(err, "failed to get matching SGP for Pods", "namespace", pod.Namespace, "name", pod.Name) return admission.Denied("Failed to get Matching SGP for Pods, rejecting event") } + if len(sgList) == 0 { return admission.Allowed("Pod didn't match any SGP") } From bbbb4599198c0f085afa5eef57626e0d71a2d08a Mon Sep 17 00:00:00 2001 From: june Date: Sun, 2 Jun 2024 04:10:16 +0900 Subject: [PATCH 12/14] add fargate sglist check --- webhooks/core/pod_webhook.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/webhooks/core/pod_webhook.go b/webhooks/core/pod_webhook.go index d55e8aab..d1d5390b 100644 --- a/webhooks/core/pod_webhook.go +++ b/webhooks/core/pod_webhook.go @@ -156,11 +156,11 @@ func (i *PodMutationWebHook) HandleFargatePod(req admission.Request, pod *corev1 default: // If more than 5 SGs match for the Pod, deny the request // Fargate only allows up to 5 security groups. If you are using Fargate, you can only use up to 5 security groups per pod - // if len(sgList) > 5 { - // log.Info("Denying request due to too many matching security groups", - // "Security Groups", sgList) - // return admission.Denied("Too many matching security groups, rejecting event") - // } + if len(sgList) > 5 { + log.Info("Denying request due to too many matching security groups", + "Security Groups", sgList) + return admission.Denied("Too many matching security groups, rejecting event") + } // If more than 1 SG match for the Pod then add all matching SG to the Annotation pod.Annotations[FargatePodSGAnnotationKey] = strings.Join(sgList, ",") log.Info("annotating Fargate pod with matching security groups", From d3c1197c2fd56245739dfaa252e1f892a3fa2fcd Mon Sep 17 00:00:00 2001 From: june Date: Sun, 2 Jun 2024 04:10:53 +0900 Subject: [PATCH 13/14] remove space --- webhooks/core/pod_webhook.go | 1 - 1 file changed, 1 deletion(-) diff --git a/webhooks/core/pod_webhook.go b/webhooks/core/pod_webhook.go index d1d5390b..a1767998 100644 --- a/webhooks/core/pod_webhook.go +++ b/webhooks/core/pod_webhook.go @@ -175,7 +175,6 @@ func (i *PodMutationWebHook) HandleFargatePod(req admission.Request, pod *corev1 // Limit to the Pod when the Windows IPAM feature is enabled via ConfigMap func (i *PodMutationWebHook) HandleWindowsPod(req admission.Request, pod *corev1.Pod, log logr.Logger) (response admission.Response) { - if !i.Condition.IsWindowsIPAMEnabled() { return admission.Allowed("") } From 6a99c219dfb79d6787dec63072b1bc126e6ae99c Mon Sep 17 00:00:00 2001 From: june Date: Sun, 2 Jun 2024 04:19:19 +0900 Subject: [PATCH 14/14] add describe --- pkg/aws/ec2/api/helper.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/aws/ec2/api/helper.go b/pkg/aws/ec2/api/helper.go index 91bd5d5f..eabff4de 100644 --- a/pkg/aws/ec2/api/helper.go +++ b/pkg/aws/ec2/api/helper.go @@ -640,6 +640,7 @@ func (h *ec2APIHelper) GetSecurityGroupQuota(quotaCode, serviceCode *string) (in } serviceQuotaOutput, err := h.ec2Wrapper.GetServiceQuota(input) if err != nil { + // Default value of security groups per network interface return 5, fmt.Errorf("failed to retrieve security group quota: %v", err) } return int(serviceQuotaOutput), nil