mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-15 17:11:30 +00:00
fix: require iam:PassRole for EKS add-on service account role
CreateAddon and UpdateAddon now pass serviceAccountRoleArn through the existing EKS PassedRoleARNs path, so the caller needs iam:PassRole on the role for eks.amazonaws.com, matching CreateCluster and CreateNodegroup.
This commit is contained in:
@@ -23,6 +23,18 @@ func PassedRoleARNs(action string, body []byte) []string {
|
||||
return nil
|
||||
}
|
||||
roleARN = input.NodeRole
|
||||
case "CreateAddon":
|
||||
input := new(eks.CreateAddonInput)
|
||||
if unmarshalIfBody(body, input) != nil {
|
||||
return nil
|
||||
}
|
||||
roleARN = input.ServiceAccountRoleArn
|
||||
case "UpdateAddon":
|
||||
input := new(eks.UpdateAddonInput)
|
||||
if unmarshalIfBody(body, input) != nil {
|
||||
return nil
|
||||
}
|
||||
roleARN = input.ServiceAccountRoleArn
|
||||
}
|
||||
if aws.StringValue(roleARN) == "" {
|
||||
return nil
|
||||
|
||||
@@ -78,12 +78,18 @@ func TestEKSRequest_InternalAddonsWireBody(t *testing.T) {
|
||||
rec.Body.String())
|
||||
}
|
||||
|
||||
// Only CreateCluster and CreateNodegroup hand a role to iam:PassRole; the add-on
|
||||
// service-account role is stored and rendered without that check.
|
||||
func TestPassedRoleARNs_AddonServiceAccountRoleIsNotChecked(t *testing.T) {
|
||||
// CreateAddon and UpdateAddon hand their service-account role to iam:PassRole,
|
||||
// same as CreateCluster's roleArn and CreateNodegroup's nodeRole; an absent
|
||||
// role passes nothing.
|
||||
func TestPassedRoleARNs_AddonServiceAccountRoleIsChecked(t *testing.T) {
|
||||
body := []byte(`{"addonName":"aws-load-balancer-controller","serviceAccountRoleArn":"arn:aws:iam::123456789012:role/alb"}`)
|
||||
assert.Empty(t, gateway_eks.PassedRoleARNs("CreateAddon", body))
|
||||
assert.Empty(t, gateway_eks.PassedRoleARNs("UpdateAddon", body))
|
||||
assert.Equal(t, []string{"arn:aws:iam::123456789012:role/alb"}, gateway_eks.PassedRoleARNs("CreateAddon", body))
|
||||
assert.Equal(t, []string{"arn:aws:iam::123456789012:role/alb"}, gateway_eks.PassedRoleARNs("UpdateAddon", body))
|
||||
|
||||
roleless := []byte(`{"addonName":"spinifex-noop"}`)
|
||||
assert.Empty(t, gateway_eks.PassedRoleARNs("CreateAddon", roleless))
|
||||
assert.Empty(t, gateway_eks.PassedRoleARNs("UpdateAddon", roleless))
|
||||
|
||||
assert.Equal(t, []string{"arn:aws:iam::123456789012:role/node"},
|
||||
gateway_eks.PassedRoleARNs("CreateNodegroup", []byte(`{"nodeRole":"arn:aws:iam::123456789012:role/node"}`)))
|
||||
}
|
||||
|
||||
@@ -160,3 +160,49 @@ func TestEKSCreateCluster_PassRole(t *testing.T) {
|
||||
)
|
||||
assertPermitted(t, dispatchEKS(t, allowed, http.MethodPost, "/clusters", body))
|
||||
}
|
||||
|
||||
func createAddonBody(roleARN string) string {
|
||||
return `{"addonName":"aws-load-balancer-controller","serviceAccountRoleArn":"` + roleARN + `"}`
|
||||
}
|
||||
|
||||
func updateAddonBody(roleARN string) string {
|
||||
return `{"serviceAccountRoleArn":"` + roleARN + `"}`
|
||||
}
|
||||
|
||||
func TestEKSCreateAddon_PassRole(t *testing.T) {
|
||||
body := createAddonBody(eksNodeRoleARN)
|
||||
|
||||
denied := eksPassRoleGateway(statement("Allow", "eks:*", "*"))
|
||||
assertDenied(t, dispatchEKS(t, denied, http.MethodPost, "/clusters/prod/addons", body))
|
||||
|
||||
allowed := eksPassRoleGateway(
|
||||
statement("Allow", "eks:*", "*"),
|
||||
statement("Allow", "iam:PassRole", eksNodeRoleARN),
|
||||
)
|
||||
assertPermitted(t, dispatchEKS(t, allowed, http.MethodPost, "/clusters/prod/addons", body))
|
||||
}
|
||||
|
||||
func TestEKSCreateAddon_NoRoleSkipsPassRole(t *testing.T) {
|
||||
gw := eksPassRoleGateway(statement("Allow", "eks:*", "*"))
|
||||
assertPermitted(t, dispatchEKS(t, gw, http.MethodPost, "/clusters/prod/addons", createAddonBody("")))
|
||||
}
|
||||
|
||||
func TestEKSUpdateAddon_PassRole(t *testing.T) {
|
||||
body := updateAddonBody(eksNodeRoleARN)
|
||||
const path = "/clusters/prod/addons/aws-load-balancer-controller/update"
|
||||
|
||||
denied := eksPassRoleGateway(statement("Allow", "eks:*", "*"))
|
||||
assertDenied(t, dispatchEKS(t, denied, http.MethodPost, path, body))
|
||||
|
||||
allowed := eksPassRoleGateway(
|
||||
statement("Allow", "eks:*", "*"),
|
||||
statement("Allow", "iam:PassRole", eksNodeRoleARN),
|
||||
)
|
||||
assertPermitted(t, dispatchEKS(t, allowed, http.MethodPost, path, body))
|
||||
}
|
||||
|
||||
func TestEKSUpdateAddon_NoRoleSkipsPassRole(t *testing.T) {
|
||||
gw := eksPassRoleGateway(statement("Allow", "eks:*", "*"))
|
||||
assertPermitted(t, dispatchEKS(t, gw, http.MethodPost,
|
||||
"/clusters/prod/addons/aws-load-balancer-controller/update", updateAddonBody("")))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user