From 16e2cdf7630579e94279a42f24b66c91afed564e Mon Sep 17 00:00:00 2001 From: Robert Russell <23439640+WarpRat@users.noreply.github.com> Date: Sun, 5 Jul 2020 15:13:10 -0700 Subject: [PATCH] Allow configurable backend modes for aws-iam-authenticator --- docs/authentication.md | 13 +- k8s/crds/kops.k8s.io_clusters.yaml | 9 ++ pkg/apis/kops/cluster.go | 4 + pkg/apis/kops/v1alpha2/cluster.go | 4 + .../kops/v1alpha2/zz_generated.conversion.go | 2 + upup/models/bindata.go | 13 ++ .../authentication.aws/k8s-1.12.yaml.template | 13 ++ .../cloudup/bootstrapchannelbuilder_test.go | 1 + upup/pkg/fi/cloudup/template_functions.go | 1 + .../authentication.aws-k8s-1.12.yaml | 153 ++++++++++++++++++ .../awsiamauthenticator/cluster.yaml | 45 ++++++ .../awsiamauthenticator/manifest.yaml | 104 ++++++++++++ 12 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/awsiamauthenticator/authentication.aws-k8s-1.12.yaml create mode 100644 upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/awsiamauthenticator/cluster.yaml create mode 100644 upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/awsiamauthenticator/manifest.yaml diff --git a/docs/authentication.md b/docs/authentication.md index 4fb7d008b09e8..a869ac9703aae 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -55,7 +55,7 @@ spec: rbac: {} ``` -The creation of a AWS IAM authenticator config as a ConfigMap is also required. +By default the creation of a AWS IAM authenticator config as a ConfigMap is also required. For more details on AWS IAM authenticator please visit [kubernetes-sigs/aws-iam-authenticator](https://github.com/kubernetes-sigs/aws-iam-authenticator) Example config: @@ -113,6 +113,17 @@ data: - system:masters ``` +It is also possible to configure alternative backend modes for aws-iam-authenticator. The `backendMode` configuration option allows defining multiple backends in a comma separated string. The mappings in these backends will be merged. When the same mapping is found in multiple backends, the first backend in the list will take precedence. If MountedFile is not included in the list of backends, no configmap is required and the [cluster-id](https://github.com/kubernetes-sigs/aws-iam-authenticator#what-is-a-cluster-id) will default to the cluster's master API DNS name. The cluster ID can be overriden by setting the `clusterID`. If you wish to continue using a configmap for authenticator settings other than mappings MountedFile will need to be included in the backendMode list. + +This requires an aws-iam-authenticator image >= 0.5.0 For more information see [usergroup-mappings](https://github.com/kubernetes-sigs/aws-iam-authenticator#4-create-iam-roleuser-to-kubernetes-usergroup-mappings) + +```yaml +authentication: + aws: + backendMode: CRD,MountedFile + clusterID: demo.cluster.us-west-2 +``` + ### Creating a new cluster with IAM Authenticator on. * Create a cluster following the [AWS getting started guide](getting_started/aws.md) diff --git a/k8s/crds/kops.k8s.io_clusters.yaml b/k8s/crds/kops.k8s.io_clusters.yaml index 7a467e9ea328b..1d9a87450049e 100644 --- a/k8s/crds/kops.k8s.io_clusters.yaml +++ b/k8s/crds/kops.k8s.io_clusters.yaml @@ -135,6 +135,15 @@ spec: properties: aws: properties: + backendMode: + description: BackendMode is the AWS IAM Authenticator backend + to use. Default MountedFile + type: string + clusterID: + description: ClusterID identifies the cluster performing authentication + to prevent certain replay attacks. Default master public + DNS name + type: string cpuLimit: anyOf: - type: integer diff --git a/pkg/apis/kops/cluster.go b/pkg/apis/kops/cluster.go index 325fb64834bf5..f2e070539bae8 100644 --- a/pkg/apis/kops/cluster.go +++ b/pkg/apis/kops/cluster.go @@ -303,6 +303,10 @@ type KopeioAuthenticationSpec struct { type AwsAuthenticationSpec struct { // Image is the AWS IAM Authenticator docker image to use Image string `json:"image,omitempty"` + // BackendMode is the AWS IAM Authenticator backend to use. Default MountedFile + BackendMode string `json:"backendMode,omitempty"` + // ClusterID identifies the cluster performing authentication to prevent certain replay attacks. Default master public DNS name + ClusterID string `json:"clusterID,omitempty"` // MemoryRequest memory request of AWS IAM Authenticator container. Default 20Mi MemoryRequest *resource.Quantity `json:"memoryRequest,omitempty"` // CPURequest CPU request of AWS IAM Authenticator container. Default 10m diff --git a/pkg/apis/kops/v1alpha2/cluster.go b/pkg/apis/kops/v1alpha2/cluster.go index c408a0100d21d..78e31e6070b1a 100644 --- a/pkg/apis/kops/v1alpha2/cluster.go +++ b/pkg/apis/kops/v1alpha2/cluster.go @@ -300,6 +300,10 @@ type KopeioAuthenticationSpec struct { type AwsAuthenticationSpec struct { // Image is the AWS IAM Authenticator docker image to uses Image string `json:"image,omitempty"` + // BackendMode is the AWS IAM Authenticator backend to use. Default MountedFile + BackendMode string `json:"backendMode,omitempty"` + // ClusterID identifies the cluster performing authentication to prevent certain replay attacks. Default master public DNS name + ClusterID string `json:"clusterID,omitempty"` // MemoryRequest memory request of AWS IAM Authenticator container. Default 20Mi MemoryRequest *resource.Quantity `json:"memoryRequest,omitempty"` // CPURequest CPU request of AWS IAM Authenticator container. Default 10m diff --git a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go index 0251cbeacd4aa..709516ce262f5 100644 --- a/pkg/apis/kops/v1alpha2/zz_generated.conversion.go +++ b/pkg/apis/kops/v1alpha2/zz_generated.conversion.go @@ -1184,6 +1184,7 @@ func Convert_kops_AuthorizationSpec_To_v1alpha2_AuthorizationSpec(in *kops.Autho func autoConvert_v1alpha2_AwsAuthenticationSpec_To_kops_AwsAuthenticationSpec(in *AwsAuthenticationSpec, out *kops.AwsAuthenticationSpec, s conversion.Scope) error { out.Image = in.Image + out.BackendMode = in.BackendMode out.MemoryRequest = in.MemoryRequest out.CPURequest = in.CPURequest out.MemoryLimit = in.MemoryLimit @@ -1198,6 +1199,7 @@ func Convert_v1alpha2_AwsAuthenticationSpec_To_kops_AwsAuthenticationSpec(in *Aw func autoConvert_kops_AwsAuthenticationSpec_To_v1alpha2_AwsAuthenticationSpec(in *kops.AwsAuthenticationSpec, out *AwsAuthenticationSpec, s conversion.Scope) error { out.Image = in.Image + out.BackendMode = in.BackendMode out.MemoryRequest = in.MemoryRequest out.CPURequest = in.CPURequest out.MemoryLimit = in.MemoryLimit diff --git a/upup/models/bindata.go b/upup/models/bindata.go index 6843c7d9afc2b..1b31d87fe038e 100644 --- a/upup/models/bindata.go +++ b/upup/models/bindata.go @@ -351,9 +351,18 @@ spec: image: {{ or .Authentication.Aws.Image "602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon/aws-iam-authenticator:v0.5.1-debian-stretch" }} args: - server + {{- if or (not .Authentication.Aws.BackendMode) (contains "MountedFile" .Authentication.Aws.BackendMode) }} - --config=/etc/aws-iam-authenticator/config.yaml + {{- end }} + {{- if or .Authentication.Aws.ClusterID (not (contains "MountedFile" .Authentication.Aws.BackendMode))}} + - --cluster-id={{ or .Authentication.Aws.ClusterID .MasterPublicName }} + {{- end }} - --state-dir=/var/aws-iam-authenticator - --kubeconfig-pregenerated=true + {{- if .Authentication.Aws.BackendMode }} + - --backend-mode={{ .Authentication.Aws.BackendMode }} + {{- end }} + resources: requests: memory: {{ or .Authentication.Aws.MemoryRequest "20Mi" }} @@ -368,16 +377,20 @@ spec: port: 21362 scheme: HTTPS volumeMounts: + {{- if or (not .Authentication.Aws.BackendMode) (contains "MountedFile" .Authentication.Aws.BackendMode) }} - name: config mountPath: /etc/aws-iam-authenticator/ + {{- end }} - name: state mountPath: /var/aws-iam-authenticator/ - name: output mountPath: /etc/kubernetes/aws-iam-authenticator/ volumes: + {{- if or (not .Authentication.Aws.BackendMode) (contains "MountedFile" .Authentication.Aws.BackendMode) }} - name: config configMap: name: aws-iam-authenticator + {{- end }} - name: output hostPath: path: /srv/kubernetes/aws-iam-authenticator/ diff --git a/upup/models/cloudup/resources/addons/authentication.aws/k8s-1.12.yaml.template b/upup/models/cloudup/resources/addons/authentication.aws/k8s-1.12.yaml.template index be79294fc7e99..6f47d215d7a76 100644 --- a/upup/models/cloudup/resources/addons/authentication.aws/k8s-1.12.yaml.template +++ b/upup/models/cloudup/resources/addons/authentication.aws/k8s-1.12.yaml.template @@ -128,9 +128,18 @@ spec: image: {{ or .Authentication.Aws.Image "602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon/aws-iam-authenticator:v0.5.1-debian-stretch" }} args: - server + {{- if or (not .Authentication.Aws.BackendMode) (contains "MountedFile" .Authentication.Aws.BackendMode) }} - --config=/etc/aws-iam-authenticator/config.yaml + {{- end }} + {{- if or .Authentication.Aws.ClusterID (not (contains "MountedFile" .Authentication.Aws.BackendMode))}} + - --cluster-id={{ or .Authentication.Aws.ClusterID .MasterPublicName }} + {{- end }} - --state-dir=/var/aws-iam-authenticator - --kubeconfig-pregenerated=true + {{- if .Authentication.Aws.BackendMode }} + - --backend-mode={{ .Authentication.Aws.BackendMode }} + {{- end }} + resources: requests: memory: {{ or .Authentication.Aws.MemoryRequest "20Mi" }} @@ -145,16 +154,20 @@ spec: port: 21362 scheme: HTTPS volumeMounts: + {{- if or (not .Authentication.Aws.BackendMode) (contains "MountedFile" .Authentication.Aws.BackendMode) }} - name: config mountPath: /etc/aws-iam-authenticator/ + {{- end }} - name: state mountPath: /var/aws-iam-authenticator/ - name: output mountPath: /etc/kubernetes/aws-iam-authenticator/ volumes: + {{- if or (not .Authentication.Aws.BackendMode) (contains "MountedFile" .Authentication.Aws.BackendMode) }} - name: config configMap: name: aws-iam-authenticator + {{- end }} - name: output hostPath: path: /srv/kubernetes/aws-iam-authenticator/ diff --git a/upup/pkg/fi/cloudup/bootstrapchannelbuilder_test.go b/upup/pkg/fi/cloudup/bootstrapchannelbuilder_test.go index cd614426dd63d..cc8e4d048780d 100644 --- a/upup/pkg/fi/cloudup/bootstrapchannelbuilder_test.go +++ b/upup/pkg/fi/cloudup/bootstrapchannelbuilder_test.go @@ -46,6 +46,7 @@ func TestBootstrapChannelBuilder_BuildTasks(t *testing.T) { runChannelBuilderTest(t, "cilium", []string{"dns-controller.addons.k8s.io-k8s-1.12", "kops-controller.addons.k8s.io-k8s-1.16"}) runChannelBuilderTest(t, "weave", []string{}) runChannelBuilderTest(t, "amazonvpc", []string{"networking.amazon-vpc-routed-eni-k8s-1.12", "networking.amazon-vpc-routed-eni-k8s-1.16"}) + runChannelBuilderTest(t, "awsiamauthenticator", []string{"authentication.aws-k8s-1.12"}) } func runChannelBuilderTest(t *testing.T, key string, addonManifests []string) { diff --git a/upup/pkg/fi/cloudup/template_functions.go b/upup/pkg/fi/cloudup/template_functions.go index 55fc8ed96307d..55c098c90318f 100644 --- a/upup/pkg/fi/cloudup/template_functions.go +++ b/upup/pkg/fi/cloudup/template_functions.go @@ -79,6 +79,7 @@ func (tf *TemplateFunctions) AddTo(dest template.FuncMap, secretStore fi.SecretS sprigTxtFuncMap := sprig.TxtFuncMap() dest["indent"] = sprigTxtFuncMap["indent"] + dest["contains"] = sprigTxtFuncMap["contains"] dest["ClusterName"] = tf.ClusterName dest["HasTag"] = tf.HasTag diff --git a/upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/awsiamauthenticator/authentication.aws-k8s-1.12.yaml b/upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/awsiamauthenticator/authentication.aws-k8s-1.12.yaml new file mode 100644 index 0000000000000..70253b9e6e489 --- /dev/null +++ b/upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/awsiamauthenticator/authentication.aws-k8s-1.12.yaml @@ -0,0 +1,153 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: iamidentitymappings.iamauthenticator.k8s.aws +spec: + group: iamauthenticator.k8s.aws + names: + categories: + - all + kind: IAMIdentityMapping + plural: iamidentitymappings + singular: iamidentitymapping + scope: Cluster + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + properties: + arn: + type: string + groups: + items: + type: string + type: array + username: + type: string + required: + - arn + - username + version: v1alpha1 + +--- + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: aws-iam-authenticator +rules: +- apiGroups: + - iamauthenticator.k8s.aws + resources: + - iamidentitymappings + verbs: + - get + - list + - watch +- apiGroups: + - iamauthenticator.k8s.aws + resources: + - iamidentitymappings/status + verbs: + - patch + - update +- apiGroups: + - "" + resources: + - events + verbs: + - create + - update + - patch + +--- + +apiVersion: v1 +kind: ServiceAccount +metadata: + name: aws-iam-authenticator + namespace: kube-system + +--- + +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: aws-iam-authenticator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: aws-iam-authenticator +subjects: +- kind: ServiceAccount + name: aws-iam-authenticator + namespace: kube-system + +--- + +apiVersion: apps/v1 +kind: DaemonSet +metadata: + labels: + k8s-app: aws-iam-authenticator + name: aws-iam-authenticator + namespace: kube-system +spec: + selector: + matchLabels: + k8s-app: aws-iam-authenticator + template: + metadata: + annotations: + scheduler.alpha.kubernetes.io/critical-pod: "" + labels: + k8s-app: aws-iam-authenticator + spec: + containers: + - args: + - server + - --cluster-id=api.minimal.example.com + - --state-dir=/var/aws-iam-authenticator + - --kubeconfig-pregenerated=true + - --backend-mode=CRD + image: 602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon/aws-iam-authenticator:v0.5.1-debian-stretch + livenessProbe: + httpGet: + host: 127.0.0.1 + path: /healthz + port: 21362 + scheme: HTTPS + name: aws-iam-authenticator + resources: + limits: + cpu: 100m + memory: 20Mi + requests: + cpu: 10m + memory: 20Mi + volumeMounts: + - mountPath: /var/aws-iam-authenticator/ + name: state + - mountPath: /etc/kubernetes/aws-iam-authenticator/ + name: output + hostNetwork: true + nodeSelector: + node-role.kubernetes.io/master: "" + priorityClassName: system-node-critical + serviceAccountName: aws-iam-authenticator + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + - key: CriticalAddonsOnly + operator: Exists + volumes: + - hostPath: + path: /srv/kubernetes/aws-iam-authenticator/ + name: output + - hostPath: + path: /srv/kubernetes/aws-iam-authenticator/ + name: state + updateStrategy: + type: RollingUpdate diff --git a/upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/awsiamauthenticator/cluster.yaml b/upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/awsiamauthenticator/cluster.yaml new file mode 100644 index 0000000000000..9c11695d57aba --- /dev/null +++ b/upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/awsiamauthenticator/cluster.yaml @@ -0,0 +1,45 @@ +apiVersion: kops.k8s.io/v1alpha2 +kind: Cluster +metadata: + creationTimestamp: "2016-12-10T22:42:27Z" + name: minimal.example.com +spec: + addons: + - manifest: s3://somebucket/example.yaml + authentication: + aws: + backendMode: CRD + kubernetesApiAccess: + - 0.0.0.0/0 + channel: stable + cloudProvider: aws + configBase: memfs://clusters.example.com/minimal.example.com + etcdClusters: + - etcdMembers: + - instanceGroup: master-us-test-1a + name: master-us-test-1a + name: main + - etcdMembers: + - instanceGroup: master-us-test-1a + name: master-us-test-1a + name: events + iam: {} + kubernetesVersion: v1.14.6 + masterInternalName: api.internal.minimal.example.com + masterPublicName: api.minimal.example.com + additionalSans: + - proxy.api.minimal.example.com + networkCIDR: 172.20.0.0/16 + networking: + kubenet: {} + nonMasqueradeCIDR: 100.64.0.0/10 + sshAccess: + - 0.0.0.0/0 + topology: + masters: public + nodes: public + subnets: + - cidr: 172.20.32.0/19 + name: us-test-1a + type: Public + zone: us-test-1a diff --git a/upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/awsiamauthenticator/manifest.yaml b/upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/awsiamauthenticator/manifest.yaml new file mode 100644 index 0000000000000..74e2828ca933d --- /dev/null +++ b/upup/pkg/fi/cloudup/tests/bootstrapchannelbuilder/awsiamauthenticator/manifest.yaml @@ -0,0 +1,104 @@ +kind: Addons +metadata: + creationTimestamp: null + name: bootstrap +spec: + addons: + - id: k8s-1.16 + kubernetesVersion: '>=1.16.0-alpha.0' + manifest: kops-controller.addons.k8s.io/k8s-1.16.yaml + manifestHash: cafdcd2b3f237ae82d0b1ccc42331480be24271d + name: kops-controller.addons.k8s.io + selector: + k8s-addon: kops-controller.addons.k8s.io + version: 1.19.0-alpha.1 + - manifest: core.addons.k8s.io/v1.4.0.yaml + manifestHash: 3ffe9ac576f9eec72e2bdfbd2ea17d56d9b17b90 + name: core.addons.k8s.io + selector: + k8s-addon: core.addons.k8s.io + version: 1.4.0 + - id: k8s-1.6 + kubernetesVersion: <1.12.0 + manifest: kube-dns.addons.k8s.io/k8s-1.6.yaml + manifestHash: dc3d42acafa02913589a75b6800ed22aa4ff97b1 + name: kube-dns.addons.k8s.io + selector: + k8s-addon: kube-dns.addons.k8s.io + version: 1.15.13-kops.2 + - id: k8s-1.12 + kubernetesVersion: '>=1.12.0' + manifest: kube-dns.addons.k8s.io/k8s-1.12.yaml + manifestHash: 90d49903e9285fc9191d7daea2f9c6a2d955443f + name: kube-dns.addons.k8s.io + selector: + k8s-addon: kube-dns.addons.k8s.io + version: 1.15.13-kops.2 + - id: k8s-1.8 + manifest: rbac.addons.k8s.io/k8s-1.8.yaml + manifestHash: 5d53ce7b920cd1e8d65d2306d80a041420711914 + name: rbac.addons.k8s.io + selector: + k8s-addon: rbac.addons.k8s.io + version: 1.8.0 + - id: k8s-1.9 + manifest: kubelet-api.rbac.addons.k8s.io/k8s-1.9.yaml + manifestHash: e1508d77cb4e527d7a2939babe36dc350dd83745 + name: kubelet-api.rbac.addons.k8s.io + selector: + k8s-addon: kubelet-api.rbac.addons.k8s.io + version: v0.0.1 + - manifest: limit-range.addons.k8s.io/v1.5.0.yaml + manifestHash: 2ea50e23f1a5aa41df3724630ac25173738cc90c + name: limit-range.addons.k8s.io + selector: + k8s-addon: limit-range.addons.k8s.io + version: 1.5.0 + - id: k8s-1.6 + kubernetesVersion: <1.12.0 + manifest: dns-controller.addons.k8s.io/k8s-1.6.yaml + manifestHash: 224077cac498b4c3a06c43e8a7689d3927e28246 + name: dns-controller.addons.k8s.io + selector: + k8s-addon: dns-controller.addons.k8s.io + version: 1.19.0-alpha.1 + - id: k8s-1.12 + kubernetesVersion: '>=1.12.0' + manifest: dns-controller.addons.k8s.io/k8s-1.12.yaml + manifestHash: c497df601c2e5a7c19f216b8b64b30282dabba9f + name: dns-controller.addons.k8s.io + selector: + k8s-addon: dns-controller.addons.k8s.io + version: 1.19.0-alpha.1 + - id: v1.15.0 + kubernetesVersion: '>=1.15.0' + manifest: storage-aws.addons.k8s.io/v1.15.0.yaml + manifestHash: 00cf6e46e25b736b2da93c6025ce482474d83904 + name: storage-aws.addons.k8s.io + selector: + k8s-addon: storage-aws.addons.k8s.io + version: 1.15.0 + - id: v1.7.0 + kubernetesVersion: <1.15.0 + manifest: storage-aws.addons.k8s.io/v1.7.0.yaml + manifestHash: 62705a596142e6cc283280e8aa973e51536994c5 + name: storage-aws.addons.k8s.io + selector: + k8s-addon: storage-aws.addons.k8s.io + version: 1.15.0 + - id: k8s-1.10 + kubernetesVersion: '>=1.10.0 <1.12.0' + manifest: authentication.aws/k8s-1.10.yaml + manifestHash: 84cbe39ff9e48669837d5074b5c0048ae9fc1a8b + name: authentication.aws + selector: + role.kubernetes.io/authentication: "1" + version: 0.4.0-kops.2 + - id: k8s-1.12 + kubernetesVersion: '>=1.12.0' + manifest: authentication.aws/k8s-1.12.yaml + manifestHash: c4f7cd3bf0b39ca7ab1b27f875da96bf5feacca9 + name: authentication.aws + selector: + role.kubernetes.io/authentication: "1" + version: 0.5.1-kops.1