mirror of https://github.com/kubernetes/kops.git
Merge pull request #12538 from hierynomus/issue-12205
Configure aws-iam-authenticator using identityMappings defined in cluster.yaml
This commit is contained in:
commit
59a637e6de
|
|
@ -55,10 +55,10 @@ spec:
|
|||
rbac: {}
|
||||
```
|
||||
|
||||
By default the creation of an AWS IAM authenticator config as a ConfigMap is also required.
|
||||
If no `backendMode` is configured, by default the `aws-iam-authenticator` will require the creation of an AWS IAM authenticator config as a ConfigMap.
|
||||
For more details on AWS IAM authenticator please visit [kubernetes-sigs/aws-iam-authenticator](https://github.com/kubernetes-sigs/aws-iam-authenticator)
|
||||
|
||||
Example config:
|
||||
Example config using a ConfigMap:
|
||||
|
||||
```yaml
|
||||
---
|
||||
|
|
@ -124,13 +124,34 @@ authentication:
|
|||
clusterID: demo.cluster.us-west-2
|
||||
```
|
||||
|
||||
When setting the `backendMode` configuration to `CRD`, it is possible to provide a list of inline AWS IAM identity mappings in the cluster template.
|
||||
|
||||
```yaml
|
||||
authentication:
|
||||
aws:
|
||||
backendMode: CRD
|
||||
clusterID: demo.cluster.us-west-2
|
||||
identityMappings:
|
||||
- arn: arn:aws:iam::000000000000:role/KubernetesAdmin
|
||||
username: admin:{{SessionName}}
|
||||
groups:
|
||||
- system:masters
|
||||
- arn: arn:aws:iam::000000000000:user/Alice
|
||||
username: alice
|
||||
groups:
|
||||
- system:masters
|
||||
```
|
||||
|
||||
### Creating a new cluster with IAM Authenticator on.
|
||||
|
||||
* Create a cluster following the [AWS getting started guide](getting_started/aws.md)
|
||||
* When you reach the "Customize Cluster Configuration" section of the guide modify the cluster spec and add the Authentication and Authorization configs to the YAML config.
|
||||
* Optionally set the `backendMode: CRD` and configure the identityMappings inline.
|
||||
* Continue following the cluster creation guide to build the cluster.
|
||||
* :warning: When the cluster first comes up the aws-iam-authenticator PODs will be in a bad state.
|
||||
as it is trying to find the aws-iam-authenticator ConfigMap and we have not yet created it.
|
||||
* :warning: When no `backendMode` is configured (or it is set to `MountedFile`) and the cluster first comes up the aws-iam-authenticator PODs will be in a bad state as it is trying to find the aws-iam-authenticator ConfigMap and we have not yet created it.
|
||||
|
||||
If no `backendMode` is configured, or it is set to `MountedFile, the following additional steps are necessary:
|
||||
|
||||
* Once the cluster is up, you'll need to create an aws-iam-authenticator configMap on the cluster `kubectl apply -f aws-iam-authenticator_example-config.yaml`
|
||||
* Once the configuration is created you need to delete the initially created aws-iam-authenticator PODs, this will force new ones to come and correctly find the ConfigMap.
|
||||
```
|
||||
|
|
@ -144,4 +165,4 @@ kubectl get pods -n kube-system | grep aws-iam-authenticator | awk '{print $1}'
|
|||
* Update the clusters configuration `kops update cluster ${CLUSTER_NAME} --yes`
|
||||
* Temporarily disable aws-iam-authenticator DaemonSet `kubectl patch daemonset -n kube-system aws-iam-authenticator -p '{"spec": {"template": {"spec": {"nodeSelector": {"disable-aws-iam-authenticator": "true"}}}}}'`
|
||||
* Perform a rolling update of the masters `kops rolling-update cluster ${CLUSTER_NAME} --instance-group-roles=Master --force --yes`
|
||||
* Re-enable aws-iam-authenticator DaemonSet `kubectl patch daemonset -n kube-system aws-iam-authenticator --type json -p='[{"op": "remove", "path": "/spec/template/spec/nodeSelector/disable-aws-iam-authenticator"}]'`
|
||||
* Re-enable aws-iam-authenticator DaemonSet `kubectl patch daemonset -n kube-system aws-iam-authenticator --type json -p='[{"op": "remove", "path": "/spec/template/spec/nodeSelector/disable-aws-iam-authenticator"}]'`
|
||||
|
|
|
|||
|
|
@ -205,6 +205,26 @@ spec:
|
|||
container. Default 10m
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
identityMappings:
|
||||
description: IdentityMappings maps IAM Identities to Kubernetes
|
||||
users/groups
|
||||
items:
|
||||
properties:
|
||||
arn:
|
||||
description: Arn of the IAM User or IAM Role to be allowed
|
||||
to authenticate
|
||||
type: string
|
||||
groups:
|
||||
description: Groups to be attached to your users/roles
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
username:
|
||||
description: Username that Kubernetes will see the user
|
||||
as
|
||||
type: string
|
||||
type: object
|
||||
type: array
|
||||
image:
|
||||
description: Image is the AWS IAM Authenticator docker image
|
||||
to uses
|
||||
|
|
|
|||
|
|
@ -373,6 +373,17 @@ type AwsAuthenticationSpec struct {
|
|||
MemoryLimit *resource.Quantity `json:"memoryLimit,omitempty"`
|
||||
// CPULimit CPU limit of AWS IAM Authenticator container. Default 10m
|
||||
CPULimit *resource.Quantity `json:"cpuLimit,omitempty"`
|
||||
// IdentityMappings maps IAM Identities to Kubernetes users/groups
|
||||
IdentityMappings []AwsAuthenticationIdentityMappingSpec `json:"identityMappings,omitempty"`
|
||||
}
|
||||
|
||||
type AwsAuthenticationIdentityMappingSpec struct {
|
||||
// Arn of the IAM User or IAM Role to be allowed to authenticate
|
||||
ARN string `json:"arn,omitempty"`
|
||||
// Username that Kubernetes will see the user as
|
||||
Username string `json:"username,omitempty"`
|
||||
// Groups to be attached to your users/roles
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
}
|
||||
|
||||
type AuthorizationSpec struct {
|
||||
|
|
|
|||
|
|
@ -371,6 +371,17 @@ type AwsAuthenticationSpec struct {
|
|||
MemoryLimit *resource.Quantity `json:"memoryLimit,omitempty"`
|
||||
// CPULimit CPU limit of AWS IAM Authenticator container. Default 10m
|
||||
CPULimit *resource.Quantity `json:"cpuLimit,omitempty"`
|
||||
// IdentityMappings maps IAM Identities to Kubernetes users/groups
|
||||
IdentityMappings []AwsAuthenticationIdentityMappingSpec `json:"identityMappings,omitempty"`
|
||||
}
|
||||
|
||||
type AwsAuthenticationIdentityMappingSpec struct {
|
||||
// Arn of the IAM User or IAM Role to be allowed to authenticate
|
||||
ARN string `json:"arn,omitempty"`
|
||||
// Username that Kubernetes will see the user as
|
||||
Username string `json:"username,omitempty"`
|
||||
// Groups to be attached to your users/roles
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
}
|
||||
|
||||
type AuthorizationSpec struct {
|
||||
|
|
|
|||
|
|
@ -144,6 +144,16 @@ func RegisterConversions(s *runtime.Scheme) error {
|
|||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*AwsAuthenticationIdentityMappingSpec)(nil), (*kops.AwsAuthenticationIdentityMappingSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha2_AwsAuthenticationIdentityMappingSpec_To_kops_AwsAuthenticationIdentityMappingSpec(a.(*AwsAuthenticationIdentityMappingSpec), b.(*kops.AwsAuthenticationIdentityMappingSpec), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kops.AwsAuthenticationIdentityMappingSpec)(nil), (*AwsAuthenticationIdentityMappingSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kops_AwsAuthenticationIdentityMappingSpec_To_v1alpha2_AwsAuthenticationIdentityMappingSpec(a.(*kops.AwsAuthenticationIdentityMappingSpec), b.(*AwsAuthenticationIdentityMappingSpec), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*AwsAuthenticationSpec)(nil), (*kops.AwsAuthenticationSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha2_AwsAuthenticationSpec_To_kops_AwsAuthenticationSpec(a.(*AwsAuthenticationSpec), b.(*kops.AwsAuthenticationSpec), scope)
|
||||
}); err != nil {
|
||||
|
|
@ -1507,6 +1517,30 @@ func Convert_kops_AuthorizationSpec_To_v1alpha2_AuthorizationSpec(in *kops.Autho
|
|||
return autoConvert_kops_AuthorizationSpec_To_v1alpha2_AuthorizationSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha2_AwsAuthenticationIdentityMappingSpec_To_kops_AwsAuthenticationIdentityMappingSpec(in *AwsAuthenticationIdentityMappingSpec, out *kops.AwsAuthenticationIdentityMappingSpec, s conversion.Scope) error {
|
||||
out.ARN = in.ARN
|
||||
out.Username = in.Username
|
||||
out.Groups = in.Groups
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha2_AwsAuthenticationIdentityMappingSpec_To_kops_AwsAuthenticationIdentityMappingSpec is an autogenerated conversion function.
|
||||
func Convert_v1alpha2_AwsAuthenticationIdentityMappingSpec_To_kops_AwsAuthenticationIdentityMappingSpec(in *AwsAuthenticationIdentityMappingSpec, out *kops.AwsAuthenticationIdentityMappingSpec, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha2_AwsAuthenticationIdentityMappingSpec_To_kops_AwsAuthenticationIdentityMappingSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kops_AwsAuthenticationIdentityMappingSpec_To_v1alpha2_AwsAuthenticationIdentityMappingSpec(in *kops.AwsAuthenticationIdentityMappingSpec, out *AwsAuthenticationIdentityMappingSpec, s conversion.Scope) error {
|
||||
out.ARN = in.ARN
|
||||
out.Username = in.Username
|
||||
out.Groups = in.Groups
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kops_AwsAuthenticationIdentityMappingSpec_To_v1alpha2_AwsAuthenticationIdentityMappingSpec is an autogenerated conversion function.
|
||||
func Convert_kops_AwsAuthenticationIdentityMappingSpec_To_v1alpha2_AwsAuthenticationIdentityMappingSpec(in *kops.AwsAuthenticationIdentityMappingSpec, out *AwsAuthenticationIdentityMappingSpec, s conversion.Scope) error {
|
||||
return autoConvert_kops_AwsAuthenticationIdentityMappingSpec_To_v1alpha2_AwsAuthenticationIdentityMappingSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha2_AwsAuthenticationSpec_To_kops_AwsAuthenticationSpec(in *AwsAuthenticationSpec, out *kops.AwsAuthenticationSpec, s conversion.Scope) error {
|
||||
out.Image = in.Image
|
||||
out.BackendMode = in.BackendMode
|
||||
|
|
@ -1515,6 +1549,17 @@ func autoConvert_v1alpha2_AwsAuthenticationSpec_To_kops_AwsAuthenticationSpec(in
|
|||
out.CPURequest = in.CPURequest
|
||||
out.MemoryLimit = in.MemoryLimit
|
||||
out.CPULimit = in.CPULimit
|
||||
if in.IdentityMappings != nil {
|
||||
in, out := &in.IdentityMappings, &out.IdentityMappings
|
||||
*out = make([]kops.AwsAuthenticationIdentityMappingSpec, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1alpha2_AwsAuthenticationIdentityMappingSpec_To_kops_AwsAuthenticationIdentityMappingSpec(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.IdentityMappings = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -1531,6 +1576,17 @@ func autoConvert_kops_AwsAuthenticationSpec_To_v1alpha2_AwsAuthenticationSpec(in
|
|||
out.CPURequest = in.CPURequest
|
||||
out.MemoryLimit = in.MemoryLimit
|
||||
out.CPULimit = in.CPULimit
|
||||
if in.IdentityMappings != nil {
|
||||
in, out := &in.IdentityMappings, &out.IdentityMappings
|
||||
*out = make([]AwsAuthenticationIdentityMappingSpec, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_kops_AwsAuthenticationIdentityMappingSpec_To_v1alpha2_AwsAuthenticationIdentityMappingSpec(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.IdentityMappings = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -284,6 +284,27 @@ func (in *AuthorizationSpec) DeepCopy() *AuthorizationSpec {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AwsAuthenticationIdentityMappingSpec) DeepCopyInto(out *AwsAuthenticationIdentityMappingSpec) {
|
||||
*out = *in
|
||||
if in.Groups != nil {
|
||||
in, out := &in.Groups, &out.Groups
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AwsAuthenticationIdentityMappingSpec.
|
||||
func (in *AwsAuthenticationIdentityMappingSpec) DeepCopy() *AwsAuthenticationIdentityMappingSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AwsAuthenticationIdentityMappingSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AwsAuthenticationSpec) DeepCopyInto(out *AwsAuthenticationSpec) {
|
||||
*out = *in
|
||||
|
|
@ -307,6 +328,13 @@ func (in *AwsAuthenticationSpec) DeepCopyInto(out *AwsAuthenticationSpec) {
|
|||
x := (*in).DeepCopy()
|
||||
*out = &x
|
||||
}
|
||||
if in.IdentityMappings != nil {
|
||||
in, out := &in.IdentityMappings, &out.IdentityMappings
|
||||
*out = make([]AwsAuthenticationIdentityMappingSpec, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -345,6 +345,17 @@ type AwsAuthenticationSpec struct {
|
|||
MemoryLimit *resource.Quantity `json:"memoryLimit,omitempty"`
|
||||
// CPULimit CPU limit of AWS IAM Authenticator container. Default 10m
|
||||
CPULimit *resource.Quantity `json:"cpuLimit,omitempty"`
|
||||
// IdentityMappings maps IAM Identities to Kubernetes users/groups
|
||||
IdentityMappings []AwsAuthenticationIdentityMappingSpec `json:"identityMappings,omitempty"`
|
||||
}
|
||||
|
||||
type AwsAuthenticationIdentityMappingSpec struct {
|
||||
// Arn of the IAM User or IAM Role to be allowed to authenticate
|
||||
ARN string `json:"arn,omitempty"`
|
||||
// Username that Kubernetes will see the user as
|
||||
Username string `json:"username,omitempty"`
|
||||
// Groups to be attached to your users/roles
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
}
|
||||
|
||||
type AuthorizationSpec struct {
|
||||
|
|
|
|||
|
|
@ -144,6 +144,16 @@ func RegisterConversions(s *runtime.Scheme) error {
|
|||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*AwsAuthenticationIdentityMappingSpec)(nil), (*kops.AwsAuthenticationIdentityMappingSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_AwsAuthenticationIdentityMappingSpec_To_kops_AwsAuthenticationIdentityMappingSpec(a.(*AwsAuthenticationIdentityMappingSpec), b.(*kops.AwsAuthenticationIdentityMappingSpec), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*kops.AwsAuthenticationIdentityMappingSpec)(nil), (*AwsAuthenticationIdentityMappingSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_kops_AwsAuthenticationIdentityMappingSpec_To_v1alpha3_AwsAuthenticationIdentityMappingSpec(a.(*kops.AwsAuthenticationIdentityMappingSpec), b.(*AwsAuthenticationIdentityMappingSpec), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*AwsAuthenticationSpec)(nil), (*kops.AwsAuthenticationSpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha3_AwsAuthenticationSpec_To_kops_AwsAuthenticationSpec(a.(*AwsAuthenticationSpec), b.(*kops.AwsAuthenticationSpec), scope)
|
||||
}); err != nil {
|
||||
|
|
@ -1457,6 +1467,30 @@ func Convert_kops_AuthorizationSpec_To_v1alpha3_AuthorizationSpec(in *kops.Autho
|
|||
return autoConvert_kops_AuthorizationSpec_To_v1alpha3_AuthorizationSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_AwsAuthenticationIdentityMappingSpec_To_kops_AwsAuthenticationIdentityMappingSpec(in *AwsAuthenticationIdentityMappingSpec, out *kops.AwsAuthenticationIdentityMappingSpec, s conversion.Scope) error {
|
||||
out.ARN = in.ARN
|
||||
out.Username = in.Username
|
||||
out.Groups = in.Groups
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha3_AwsAuthenticationIdentityMappingSpec_To_kops_AwsAuthenticationIdentityMappingSpec is an autogenerated conversion function.
|
||||
func Convert_v1alpha3_AwsAuthenticationIdentityMappingSpec_To_kops_AwsAuthenticationIdentityMappingSpec(in *AwsAuthenticationIdentityMappingSpec, out *kops.AwsAuthenticationIdentityMappingSpec, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha3_AwsAuthenticationIdentityMappingSpec_To_kops_AwsAuthenticationIdentityMappingSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_kops_AwsAuthenticationIdentityMappingSpec_To_v1alpha3_AwsAuthenticationIdentityMappingSpec(in *kops.AwsAuthenticationIdentityMappingSpec, out *AwsAuthenticationIdentityMappingSpec, s conversion.Scope) error {
|
||||
out.ARN = in.ARN
|
||||
out.Username = in.Username
|
||||
out.Groups = in.Groups
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_kops_AwsAuthenticationIdentityMappingSpec_To_v1alpha3_AwsAuthenticationIdentityMappingSpec is an autogenerated conversion function.
|
||||
func Convert_kops_AwsAuthenticationIdentityMappingSpec_To_v1alpha3_AwsAuthenticationIdentityMappingSpec(in *kops.AwsAuthenticationIdentityMappingSpec, out *AwsAuthenticationIdentityMappingSpec, s conversion.Scope) error {
|
||||
return autoConvert_kops_AwsAuthenticationIdentityMappingSpec_To_v1alpha3_AwsAuthenticationIdentityMappingSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha3_AwsAuthenticationSpec_To_kops_AwsAuthenticationSpec(in *AwsAuthenticationSpec, out *kops.AwsAuthenticationSpec, s conversion.Scope) error {
|
||||
out.Image = in.Image
|
||||
out.BackendMode = in.BackendMode
|
||||
|
|
@ -1465,6 +1499,17 @@ func autoConvert_v1alpha3_AwsAuthenticationSpec_To_kops_AwsAuthenticationSpec(in
|
|||
out.CPURequest = in.CPURequest
|
||||
out.MemoryLimit = in.MemoryLimit
|
||||
out.CPULimit = in.CPULimit
|
||||
if in.IdentityMappings != nil {
|
||||
in, out := &in.IdentityMappings, &out.IdentityMappings
|
||||
*out = make([]kops.AwsAuthenticationIdentityMappingSpec, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1alpha3_AwsAuthenticationIdentityMappingSpec_To_kops_AwsAuthenticationIdentityMappingSpec(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.IdentityMappings = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -1481,6 +1526,17 @@ func autoConvert_kops_AwsAuthenticationSpec_To_v1alpha3_AwsAuthenticationSpec(in
|
|||
out.CPURequest = in.CPURequest
|
||||
out.MemoryLimit = in.MemoryLimit
|
||||
out.CPULimit = in.CPULimit
|
||||
if in.IdentityMappings != nil {
|
||||
in, out := &in.IdentityMappings, &out.IdentityMappings
|
||||
*out = make([]AwsAuthenticationIdentityMappingSpec, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_kops_AwsAuthenticationIdentityMappingSpec_To_v1alpha3_AwsAuthenticationIdentityMappingSpec(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.IdentityMappings = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -285,6 +285,27 @@ func (in *AuthorizationSpec) DeepCopy() *AuthorizationSpec {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AwsAuthenticationIdentityMappingSpec) DeepCopyInto(out *AwsAuthenticationIdentityMappingSpec) {
|
||||
*out = *in
|
||||
if in.Groups != nil {
|
||||
in, out := &in.Groups, &out.Groups
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AwsAuthenticationIdentityMappingSpec.
|
||||
func (in *AwsAuthenticationIdentityMappingSpec) DeepCopy() *AwsAuthenticationIdentityMappingSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AwsAuthenticationIdentityMappingSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AwsAuthenticationSpec) DeepCopyInto(out *AwsAuthenticationSpec) {
|
||||
*out = *in
|
||||
|
|
@ -308,6 +329,13 @@ func (in *AwsAuthenticationSpec) DeepCopyInto(out *AwsAuthenticationSpec) {
|
|||
x := (*in).DeepCopy()
|
||||
*out = &x
|
||||
}
|
||||
if in.IdentityMappings != nil {
|
||||
in, out := &in.IdentityMappings, &out.IdentityMappings
|
||||
*out = make([]AwsAuthenticationIdentityMappingSpec, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/arn"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
|
@ -43,6 +44,10 @@ func awsValidateCluster(c *kops.Cluster) field.ErrorList {
|
|||
|
||||
allErrs = append(allErrs, awsValidateExternalCloudControllerManager(c)...)
|
||||
|
||||
if c.Spec.Authentication != nil && c.Spec.Authentication.Aws != nil {
|
||||
allErrs = append(allErrs, awsValidateIAMAuthenticator(field.NewPath("spec", "authentication", "aws"), c.Spec.Authentication.Aws)...)
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
|
@ -319,6 +324,22 @@ func awsValidateCPUCredits(fieldPath *field.Path, spec *kops.InstanceGroupSpec,
|
|||
return allErrs
|
||||
}
|
||||
|
||||
func awsValidateIAMAuthenticator(fieldPath *field.Path, spec *kops.AwsAuthenticationSpec) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if !strings.Contains(spec.BackendMode, "CRD") && len(spec.IdentityMappings) > 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(fieldPath.Child("backendMode"), "backendMode must be CRD if identityMappings is set"))
|
||||
}
|
||||
for i, mapping := range spec.IdentityMappings {
|
||||
parsedARN, err := arn.Parse(mapping.ARN)
|
||||
if err != nil || (!strings.HasPrefix(parsedARN.Resource, "role/") && !strings.HasPrefix(parsedARN.Resource, "user/")) {
|
||||
allErrs = append(allErrs, field.Invalid(fieldPath.Child("identityMappings").Index(i).Child("arn"), mapping.ARN,
|
||||
"arn must be a valid IAM Role or User ARN such as arn:aws:iam::123456789012:role/KopsExampleRole"))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func hasAWSEBSCSIDriver(c kops.ClusterSpec) bool {
|
||||
// AWSEBSCSIDriver will have a default value, so if this is all false, it will be populated on next pass
|
||||
if c.CloudConfig == nil || c.CloudConfig.AWSEBSCSIDriver == nil || c.CloudConfig.AWSEBSCSIDriver.Enabled == nil {
|
||||
|
|
|
|||
|
|
@ -575,3 +575,73 @@ func TestLoadBalancerSubnets(t *testing.T) {
|
|||
testErrors(t, test, errs, test.expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAWSAuthentication(t *testing.T) {
|
||||
tests := []struct {
|
||||
backendMode string
|
||||
identityMappings []kops.AwsAuthenticationIdentityMappingSpec
|
||||
expected []string
|
||||
}{
|
||||
{ // valid
|
||||
backendMode: "CRD",
|
||||
identityMappings: []kops.AwsAuthenticationIdentityMappingSpec{
|
||||
{
|
||||
ARN: "arn:aws:iam::123456789012:role/KopsExampleRole",
|
||||
Username: "foo",
|
||||
},
|
||||
{
|
||||
ARN: "arn:aws:iam::123456789012:user/KopsExampleUser",
|
||||
Username: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
{ // valid, multiple backendModes
|
||||
backendMode: "CRD,MountedFile",
|
||||
identityMappings: []kops.AwsAuthenticationIdentityMappingSpec{
|
||||
{
|
||||
ARN: "arn:aws:iam::123456789012:role/KopsExampleRole",
|
||||
Username: "foo",
|
||||
},
|
||||
{
|
||||
ARN: "arn:aws:iam::123456789012:user/KopsExampleUser",
|
||||
Username: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
{ // forbidden backendMode
|
||||
backendMode: "MountedFile",
|
||||
identityMappings: []kops.AwsAuthenticationIdentityMappingSpec{
|
||||
{
|
||||
ARN: "arn:aws:iam::123456789012:role/KopsExampleRole",
|
||||
Username: "foo",
|
||||
},
|
||||
},
|
||||
expected: []string{"Forbidden::spec.authentication.aws.backendMode"},
|
||||
},
|
||||
{ // invalid identity ARN
|
||||
backendMode: "CRD",
|
||||
identityMappings: []kops.AwsAuthenticationIdentityMappingSpec{
|
||||
{
|
||||
ARN: "arn:aws:iam::123456789012:policy/KopsExampleRole",
|
||||
Username: "foo",
|
||||
},
|
||||
},
|
||||
expected: []string{"Invalid value::spec.authentication.aws.identityMappings[0].arn"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
cluster := kops.Cluster{
|
||||
Spec: kops.ClusterSpec{
|
||||
Authentication: &kops.AuthenticationSpec{
|
||||
Aws: &kops.AwsAuthenticationSpec{
|
||||
BackendMode: test.backendMode,
|
||||
IdentityMappings: test.identityMappings,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
errs := awsValidateCluster(&cluster)
|
||||
testErrors(t, test, errs, test.expected)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -284,6 +284,27 @@ func (in *AuthorizationSpec) DeepCopy() *AuthorizationSpec {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AwsAuthenticationIdentityMappingSpec) DeepCopyInto(out *AwsAuthenticationIdentityMappingSpec) {
|
||||
*out = *in
|
||||
if in.Groups != nil {
|
||||
in, out := &in.Groups, &out.Groups
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AwsAuthenticationIdentityMappingSpec.
|
||||
func (in *AwsAuthenticationIdentityMappingSpec) DeepCopy() *AwsAuthenticationIdentityMappingSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AwsAuthenticationIdentityMappingSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AwsAuthenticationSpec) DeepCopyInto(out *AwsAuthenticationSpec) {
|
||||
*out = *in
|
||||
|
|
@ -307,6 +328,13 @@ func (in *AwsAuthenticationSpec) DeepCopyInto(out *AwsAuthenticationSpec) {
|
|||
x := (*in).DeepCopy()
|
||||
*out = &x
|
||||
}
|
||||
if in.IdentityMappings != nil {
|
||||
in, out := &in.IdentityMappings, &out.IdentityMappings
|
||||
*out = make([]AwsAuthenticationIdentityMappingSpec, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -205,3 +205,19 @@ spec:
|
|||
- name: state
|
||||
hostPath:
|
||||
path: /srv/kubernetes/aws-iam-authenticator/
|
||||
{{- if and (and (.Authentication.Aws.BackendMode) (contains "CRD" .Authentication.Aws.BackendMode)) (.Authentication.Aws.IdentityMappings) }}
|
||||
---
|
||||
{{- range $i, $mapping := .Authentication.Aws.IdentityMappings }}
|
||||
apiVersion: iamauthenticator.k8s.aws/v1alpha1
|
||||
kind: IAMIdentityMapping
|
||||
metadata:
|
||||
name: iam-identity-mapping-{{ $i }}
|
||||
labels:
|
||||
k8s-app: aws-iam-authenticator
|
||||
spec:
|
||||
arn: {{ $mapping.ARN }}
|
||||
username: {{ $mapping.Username }}
|
||||
groups:
|
||||
{{ ToYAML $mapping.Groups | indent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ func TestBootstrapChannelBuilder_BuildTasks(t *testing.T) {
|
|||
runChannelBuilderTest(t, "weave", []string{})
|
||||
runChannelBuilderTest(t, "amazonvpc", []string{"networking.amazon-vpc-routed-eni-k8s-1.16"})
|
||||
runChannelBuilderTest(t, "amazonvpc-containerd", []string{"networking.amazon-vpc-routed-eni-k8s-1.16"})
|
||||
runChannelBuilderTest(t, "awsiamauthenticator", []string{"authentication.aws-k8s-1.12"})
|
||||
runChannelBuilderTest(t, "awsiamauthenticator/crd", []string{"authentication.aws-k8s-1.12"})
|
||||
runChannelBuilderTest(t, "awsiamauthenticator/mappings", []string{"authentication.aws-k8s-1.12"})
|
||||
runChannelBuilderTest(t, "metrics-server/insecure-1.18", []string{"metrics-server.addons.k8s.io-k8s-1.11"})
|
||||
runChannelBuilderTest(t, "metrics-server/insecure-1.19", []string{"metrics-server.addons.k8s.io-k8s-1.11"})
|
||||
runChannelBuilderTest(t, "metrics-server/secure-1.18", []string{"metrics-server.addons.k8s.io-k8s-1.11"})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,226 @@
|
|||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
addon.kops.k8s.io/name: authentication.aws
|
||||
app.kubernetes.io/managed-by: kops
|
||||
role.kubernetes.io/authentication: "1"
|
||||
name: iamidentitymappings.iamauthenticator.k8s.aws
|
||||
spec:
|
||||
group: iamauthenticator.k8s.aws
|
||||
names:
|
||||
categories:
|
||||
- all
|
||||
kind: IAMIdentityMapping
|
||||
plural: iamidentitymappings
|
||||
singular: iamidentitymapping
|
||||
scope: Cluster
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
properties:
|
||||
spec:
|
||||
properties:
|
||||
arn:
|
||||
type: string
|
||||
groups:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
username:
|
||||
type: string
|
||||
required:
|
||||
- arn
|
||||
- username
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
|
||||
---
|
||||
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
addon.kops.k8s.io/name: authentication.aws
|
||||
app.kubernetes.io/managed-by: kops
|
||||
role.kubernetes.io/authentication: "1"
|
||||
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
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- configmaps
|
||||
verbs:
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- ""
|
||||
resourceNames:
|
||||
- aws-auth
|
||||
resources:
|
||||
- configmaps
|
||||
verbs:
|
||||
- get
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
addon.kops.k8s.io/name: authentication.aws
|
||||
app.kubernetes.io/managed-by: kops
|
||||
role.kubernetes.io/authentication: "1"
|
||||
name: aws-iam-authenticator
|
||||
namespace: kube-system
|
||||
|
||||
---
|
||||
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
addon.kops.k8s.io/name: authentication.aws
|
||||
app.kubernetes.io/managed-by: kops
|
||||
role.kubernetes.io/authentication: "1"
|
||||
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:
|
||||
annotations:
|
||||
seccomp.security.alpha.kubernetes.io/pod: runtime/default
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
addon.kops.k8s.io/name: authentication.aws
|
||||
app.kubernetes.io/managed-by: kops
|
||||
k8s-app: aws-iam-authenticator
|
||||
role.kubernetes.io/authentication: "1"
|
||||
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=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.3-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
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
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
|
||||
- effect: NoSchedule
|
||||
key: node-role.kubernetes.io/api-server
|
||||
- key: node.cloudprovider.kubernetes.io/uninitialized
|
||||
operator: Exists
|
||||
- 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
|
||||
|
||||
---
|
||||
|
||||
apiVersion: iamauthenticator.k8s.aws/v1alpha1
|
||||
kind: IAMIdentityMapping
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
addon.kops.k8s.io/name: authentication.aws
|
||||
app.kubernetes.io/managed-by: kops
|
||||
k8s-app: aws-iam-authenticator
|
||||
role.kubernetes.io/authentication: "1"
|
||||
name: iam-identity-mapping-0
|
||||
spec:
|
||||
arn: arn:aws:iam::00000000:role/AdminRole
|
||||
groups:
|
||||
- system:masters
|
||||
username: administrators:{{SessionName}}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
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
|
||||
identityMappings:
|
||||
- arn: arn:aws:iam::00000000:role/AdminRole
|
||||
username: administrators:{{SessionName}}
|
||||
groups:
|
||||
- system:masters
|
||||
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.20.0
|
||||
masterInternalName: api.internal.minimal.example.com
|
||||
masterPublicName: api.minimal.example.com
|
||||
additionalSans:
|
||||
- proxy.api.minimal.example.com
|
||||
networkCIDR: 172.20.0.0/16
|
||||
networking:
|
||||
cni: {}
|
||||
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
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
kind: Addons
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
name: bootstrap
|
||||
spec:
|
||||
addons:
|
||||
- id: k8s-1.16
|
||||
manifest: kops-controller.addons.k8s.io/k8s-1.16.yaml
|
||||
manifestHash: 46120dbd8151e5dffad79c48273eb910ff42fa4e05f40f76a39d554d77497f6d
|
||||
name: kops-controller.addons.k8s.io
|
||||
needsRollingUpdate: control-plane
|
||||
selector:
|
||||
k8s-addon: kops-controller.addons.k8s.io
|
||||
version: 9.99.0
|
||||
- manifest: core.addons.k8s.io/v1.4.0.yaml
|
||||
manifestHash: 18233793a8442224d052e44891e737c67ccfb4e051e95216392319653f4cb0e5
|
||||
name: core.addons.k8s.io
|
||||
selector:
|
||||
k8s-addon: core.addons.k8s.io
|
||||
version: 9.99.0
|
||||
- id: k8s-1.12
|
||||
manifest: coredns.addons.k8s.io/k8s-1.12.yaml
|
||||
manifestHash: 88ffe1a3752cf290450cc94bd53aea49a665e411dbf4cfe9c1a2cc5b027f12ef
|
||||
name: coredns.addons.k8s.io
|
||||
selector:
|
||||
k8s-addon: coredns.addons.k8s.io
|
||||
version: 9.99.0
|
||||
- id: k8s-1.9
|
||||
manifest: kubelet-api.rbac.addons.k8s.io/k8s-1.9.yaml
|
||||
manifestHash: 01c120e887bd98d82ef57983ad58a0b22bc85efb48108092a24c4b82e4c9ea81
|
||||
name: kubelet-api.rbac.addons.k8s.io
|
||||
selector:
|
||||
k8s-addon: kubelet-api.rbac.addons.k8s.io
|
||||
version: 9.99.0
|
||||
- manifest: limit-range.addons.k8s.io/v1.5.0.yaml
|
||||
manifestHash: 2d55c3bc5e354e84a3730a65b42f39aba630a59dc8d32b30859fcce3d3178bc2
|
||||
name: limit-range.addons.k8s.io
|
||||
selector:
|
||||
k8s-addon: limit-range.addons.k8s.io
|
||||
version: 9.99.0
|
||||
- id: k8s-1.12
|
||||
manifest: dns-controller.addons.k8s.io/k8s-1.12.yaml
|
||||
manifestHash: 08d576cf7e30936c5a077d9d8439f1a7a1245e737722faa477eb734e87b292aa
|
||||
name: dns-controller.addons.k8s.io
|
||||
selector:
|
||||
k8s-addon: dns-controller.addons.k8s.io
|
||||
version: 9.99.0
|
||||
- id: v1.15.0
|
||||
manifest: storage-aws.addons.k8s.io/v1.15.0.yaml
|
||||
manifestHash: 065ae832ddac8d0931e9992d6a76f43a33a36975a38003b34f4c5d86a7d42780
|
||||
name: storage-aws.addons.k8s.io
|
||||
selector:
|
||||
k8s-addon: storage-aws.addons.k8s.io
|
||||
version: 9.99.0
|
||||
- id: k8s-1.12
|
||||
manifest: authentication.aws/k8s-1.12.yaml
|
||||
manifestHash: 0cfdcbd7be8aa8a99c0e23b9417bf1c0e23bdbb5a5702168ff26f9248284ce8d
|
||||
name: authentication.aws
|
||||
selector:
|
||||
role.kubernetes.io/authentication: "1"
|
||||
version: 9.99.0
|
||||
Loading…
Reference in New Issue