Skip to content

Commit

Permalink
Add support for IRSA in he api
Browse files Browse the repository at this point in the history
  • Loading branch information
Ole Markus With committed Apr 5, 2021
1 parent 79d4f6e commit f80cd0e
Show file tree
Hide file tree
Showing 32 changed files with 2,132 additions and 16 deletions.
15 changes: 14 additions & 1 deletion cmd/kops/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,20 @@ func TestAPIServerNodes(t *testing.T) {
newIntegrationTest("minimal.example.com", "apiservernodes").runTestCloudformation(t)
}

// TestPublicIRSA runs a simple configuration, but with some additional IAM roles for ServiceAccounts
func TestIRSA(t *testing.T) {
featureflag.ParseFlags("+UseServiceAccountIAM")
unsetFeatureFlags := func() {
featureflag.ParseFlags("-UseServiceAccountIAM")
}
defer unsetFeatureFlags()
newIntegrationTest("minimal.example.com", "irsa").
withServiceAccountRole("dns-controller.kube-system", true).
withServiceAccountRole("myserviceaccount.default", false).
withServiceAccountRole("myotherserviceaccount.myapp", true).
runTestTerraformAWS(t)
}

func (i *integrationTest) runTest(t *testing.T, h *testutils.IntegrationTestHarness, expectedDataFilenames []string, tfFileName string, expectedTfFileName string, phase *cloudup.Phase) {
ctx := context.Background()

Expand Down Expand Up @@ -580,7 +594,6 @@ func (i *integrationTest) runTestTerraformAWS(t *testing.T) {
}
}
}

expectedFilenames = append(expectedFilenames, i.expectServiceAccountRolePolicies...)

i.runTest(t, h, expectedFilenames, tfFileName, tfFileName, nil)
Expand Down
20 changes: 20 additions & 0 deletions k8s/crds/kops.k8s.io_clusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,26 @@ spec:
required:
- legacy
type: object
iamRolesForServiceAccounts:
description: IAMRolesForServiceAccount defines the IRSA configuration.
properties:
serviceAccounts:
items:
properties:
iamPolicyARN:
type: string
inlinePolicy:
type: string
name:
type: string
namespace:
type: string
required:
- name
- namespace
type: object
type: array
type: object
isolateMasters:
description: 'IsolateMasters determines whether we should lock down
masters so that they are not on the pod network. true is the kube-up
Expand Down
15 changes: 15 additions & 0 deletions pkg/apis/kops/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,21 @@ type ClusterSpec struct {
RollingUpdate *RollingUpdate `json:"rollingUpdate,omitempty"`
// ClusterAutoscaler defines the cluster autoscaler configuration.
ClusterAutoscaler *ClusterAutoscalerConfig `json:"clusterAutoscaler,omitempty"`

// IAMRolesForServiceAccount defines the IRSA configuration.
IAMRolesForServiceAccounts *IAMRolesForServiceAccountsConfig `json:"iamRolesForServiceAccounts,omitempty"`
}

// InstanceRoleForServiceAccountConfig defines the IRSA configuration.
type IAMRolesForServiceAccountsConfig struct {
ServiceAccounts []ServiceAccountMapping `json:"serviceAccounts,omitempty"`
}

type ServiceAccountMapping struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
IAMPolicyARN string `json:"iamPolicyARN,omitempty"`
InlinePolicy string `json:"inlinePolicy,omitempty"`
}

// NodeAuthorizationSpec is used to node authorization
Expand Down
15 changes: 15 additions & 0 deletions pkg/apis/kops/v1alpha2/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,21 @@ type ClusterSpec struct {
RollingUpdate *RollingUpdate `json:"rollingUpdate,omitempty"`
// ClusterAutoscaler defines the cluaster autoscaler configuration.
ClusterAutoscaler *ClusterAutoscalerConfig `json:"clusterAutoscaler,omitempty"`

// IAMRolesForServiceAccount defines the IRSA configuration.
IAMRolesForServiceAccounts *IAMRolesForServiceAccountsConfig `json:"iamRolesForServiceAccounts,omitempty"`
}

// IAMRoleForServiceAccountConfig defines the IRSA configuration.
type IAMRolesForServiceAccountsConfig struct {
ServiceAccounts []ServiceAccountMapping `json:"serviceAccounts,omitempty"`
}

type ServiceAccountMapping struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
IAMPolicyARN string `json:"iamPolicyARN,omitempty"`
InlinePolicy string `json:"inlinePolicy,omitempty"`
}

// NodeAuthorizationSpec is used to node authorization
Expand Down
104 changes: 104 additions & 0 deletions pkg/apis/kops/v1alpha2/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/apis/kops/validation/BUILD.bazel

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions pkg/apis/kops/validation/legacy.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,34 @@ func ValidateCluster(c *kops.Cluster, strict bool) field.ErrorList {
}
}

if c.Spec.IAMRolesForServiceAccounts != nil {
allErrs = append(allErrs, validateIRSA(c.Spec.IAMRolesForServiceAccounts, fieldSpec.Child("iamRolesForServiceAccounts"))...)
}
return allErrs
}

func validateIRSA(irsa *kops.IAMRolesForServiceAccountsConfig, spec *field.Path) (allErrs field.ErrorList) {
if !featureflag.UseServiceAccountIAM.Enabled() {
allErrs = append(allErrs, field.Forbidden(spec, "IAM roles for ServiceAccounts requires UseServiceAccountIAM feature flag to be enabled"))
}

sas := make(map[string]string)
for _, sa := range irsa.ServiceAccounts {
p := spec.Child("serviceAccounts")
key := fmt.Sprintf("%s/%s", sa.Namespace, sa.Name)
_, duplicate := sas[key]
if duplicate {
allErrs = append(allErrs, field.Duplicate(p, key))
}
sas[key] = ""

if sa.IAMPolicyARN == "" && sa.InlinePolicy == "" {
allErrs = append(allErrs, field.Required(p, "inlinePolicy or iamPolicyARN must be set"))
}
if sa.IAMPolicyARN != "" && sa.InlinePolicy != "" {
allErrs = append(allErrs, field.Forbidden(p, "cannot set both inlinePolicy and iamPolicyARN"))
}
}
return allErrs
}

Expand Down
Loading

0 comments on commit f80cd0e

Please sign in to comment.