mirror of https://github.com/kubernetes/kops.git
Setup heptio authenticator
This commit is contained in:
parent
ee8252e323
commit
5ce8f9e712
|
@ -32,3 +32,84 @@ spec:
|
||||||
rbac: {}
|
rbac: {}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Heptio Authenticator for AWS
|
||||||
|
|
||||||
|
If you want to turn on Heptio Authenticator for AWS, you can add this block
|
||||||
|
to your cluster:
|
||||||
|
|
||||||
|
```
|
||||||
|
authentication:
|
||||||
|
heptio: {}
|
||||||
|
```
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
apiVersion: kops/v1alpha2
|
||||||
|
kind: Cluster
|
||||||
|
metadata:
|
||||||
|
name: cluster.example.com
|
||||||
|
spec:
|
||||||
|
authentication:
|
||||||
|
heptio: {}
|
||||||
|
authorization:
|
||||||
|
rbac: {}
|
||||||
|
```
|
||||||
|
|
||||||
|
Once the cluster is up you will need to create the heptio authenticator
|
||||||
|
config as a config map. (This can also be done when boostrapping a cluster using addons)
|
||||||
|
For more details on heptio authenticator please visit (heptio/authenticator)[https://github.com/heptio/authenticator]
|
||||||
|
Example config:
|
||||||
|
|
||||||
|
```
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
namespace: kube-system
|
||||||
|
name: heptio-authenticator-aws
|
||||||
|
labels:
|
||||||
|
k8s-app: heptio-authenticator-aws
|
||||||
|
data:
|
||||||
|
config.yaml: |
|
||||||
|
# a unique-per-cluster identifier to prevent replay attacks
|
||||||
|
# (good choices are a random token or a domain name that will be unique to your cluster)
|
||||||
|
clusterID: my-dev-cluster.example.com
|
||||||
|
server:
|
||||||
|
# each mapRoles entry maps an IAM role to a username and set of groups
|
||||||
|
# Each username and group can optionally contain template parameters:
|
||||||
|
# 1) "{{AccountID}}" is the 12 digit AWS ID.
|
||||||
|
# 2) "{{SessionName}}" is the role session name.
|
||||||
|
mapRoles:
|
||||||
|
# statically map arn:aws:iam::000000000000:role/KubernetesAdmin to a cluster admin
|
||||||
|
- roleARN: arn:aws:iam::000000000000:role/KubernetesAdmin
|
||||||
|
username: kubernetes-admin
|
||||||
|
groups:
|
||||||
|
- system:masters
|
||||||
|
# map EC2 instances in my "KubernetesNode" role to users like
|
||||||
|
# "aws:000000000000:instance:i-0123456789abcdef0". Only use this if you
|
||||||
|
# trust that the role can only be assumed by EC2 instances. If an IAM user
|
||||||
|
# can assume this role directly (with sts:AssumeRole) they can control
|
||||||
|
# SessionName.
|
||||||
|
- roleARN: arn:aws:iam::000000000000:role/KubernetesNode
|
||||||
|
username: aws:{{AccountID}}:instance:{{SessionName}}
|
||||||
|
groups:
|
||||||
|
- system:bootstrappers
|
||||||
|
- aws:instances
|
||||||
|
# map federated users in my "KubernetesAdmin" role to users like
|
||||||
|
# "admin:alice-example.com". The SessionName is an arbitrary role name
|
||||||
|
# like an e-mail address passed by the identity provider. Note that if this
|
||||||
|
# role is assumed directly by an IAM User (not via federation), the user
|
||||||
|
# can control the SessionName.
|
||||||
|
- roleARN: arn:aws:iam::000000000000:role/KubernetesAdmin
|
||||||
|
username: admin:{{SessionName}}
|
||||||
|
groups:
|
||||||
|
- system:masters
|
||||||
|
# each mapUsers entry maps an IAM role to a static username and set of groups
|
||||||
|
mapUsers:
|
||||||
|
# map user IAM user Alice in 000000000000 to user "alice" in "system:masters"
|
||||||
|
- userARN: arn:aws:iam::000000000000:user/Alice
|
||||||
|
username: alice
|
||||||
|
groups:
|
||||||
|
- system:masters
|
||||||
|
```
|
|
@ -157,6 +157,103 @@ func (b *KubeAPIServerBuilder) writeAuthenticationConfig(c *fi.ModelBuilderConte
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if b.Cluster.Spec.Authentication.Heptio != nil {
|
||||||
|
id := "heptio-authenticator-aws"
|
||||||
|
b.Cluster.Spec.KubeAPIServer.AuthenticationTokenWebhookConfigFile = fi.String(PathAuthnConfig)
|
||||||
|
|
||||||
|
{
|
||||||
|
caCertificate, err := b.NodeupModelContext.KeyStore.FindCert(fi.CertificateId_CA)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error fetching Heptio Authentication CA certificate from keystore: %v", err)
|
||||||
|
}
|
||||||
|
if caCertificate == nil {
|
||||||
|
return fmt.Errorf("Heptio Authentication CA certificate %q not found", fi.CertificateId_CA)
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster := kubeconfig.KubectlCluster{
|
||||||
|
Server: "https://127.0.0.1:21362/authenticate",
|
||||||
|
}
|
||||||
|
context := kubeconfig.KubectlContext{
|
||||||
|
Cluster: "heptio-authenticator-aws",
|
||||||
|
User: "kube-apiserver",
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster.CertificateAuthorityData, err = caCertificate.AsBytes()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error encoding Heptio Authentication CA certificate: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
config := kubeconfig.KubectlConfig{}
|
||||||
|
config.Clusters = append(config.Clusters, &kubeconfig.KubectlClusterWithName{
|
||||||
|
Name: "heptio-authenticator-aws",
|
||||||
|
Cluster: cluster,
|
||||||
|
})
|
||||||
|
config.Users = append(config.Users, &kubeconfig.KubectlUserWithName{
|
||||||
|
Name: "kube-apiserver",
|
||||||
|
})
|
||||||
|
config.CurrentContext = "webhook"
|
||||||
|
config.Contexts = append(config.Contexts, &kubeconfig.KubectlContextWithName{
|
||||||
|
Name: "webhook",
|
||||||
|
Context: context,
|
||||||
|
})
|
||||||
|
|
||||||
|
manifest, err := kops.ToRawYaml(config)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error marshalling authentication config to yaml: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.AddTask(&nodetasks.File{
|
||||||
|
Path: PathAuthnConfig,
|
||||||
|
Contents: fi.NewBytesResource(manifest),
|
||||||
|
Type: nodetasks.FileType_File,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
certificate, err := b.NodeupModelContext.KeyStore.FindCert(id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error fetching %q certificate from keystore: %v", id, err)
|
||||||
|
}
|
||||||
|
if certificate == nil {
|
||||||
|
return fmt.Errorf("certificate %q not found", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
certificateData, err := certificate.AsBytes()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error encoding %q certificate: %v", id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.AddTask(&nodetasks.File{
|
||||||
|
Path: "/srv/kubernetes/heptio-authenticator-aws/cert.pem",
|
||||||
|
Contents: fi.NewBytesResource(certificateData),
|
||||||
|
Type: nodetasks.FileType_File,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
privateKey, err := b.NodeupModelContext.KeyStore.FindPrivateKey(id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error fetching %q private key from keystore: %v", id, err)
|
||||||
|
}
|
||||||
|
if privateKey == nil {
|
||||||
|
return fmt.Errorf("private key %q not found", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
keyData, err := privateKey.AsBytes()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error encoding %q private key: %v", id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.AddTask(&nodetasks.File{
|
||||||
|
Path: "/srv/kubernetes/heptio-authenticator-aws/key.pem",
|
||||||
|
Contents: fi.NewBytesResource(keyData),
|
||||||
|
Type: nodetasks.FileType_File,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Unrecognized authentication config %v", b.Cluster.Spec.Authentication)
|
return fmt.Errorf("Unrecognized authentication config %v", b.Cluster.Spec.Authentication)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +408,7 @@ func (b *KubeAPIServerBuilder) buildPod() (*v1.Pod, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.Cluster.Spec.Authentication != nil {
|
if b.Cluster.Spec.Authentication != nil {
|
||||||
if b.Cluster.Spec.Authentication.Kopeio != nil {
|
if b.Cluster.Spec.Authentication.Kopeio != nil || b.Cluster.Spec.Authentication.Heptio != nil {
|
||||||
addHostPathMapping(pod, container, "authn-config", PathAuthnConfig)
|
addHostPathMapping(pod, container, "authn-config", PathAuthnConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,15 +230,19 @@ type ExecContainerAction struct {
|
||||||
|
|
||||||
type AuthenticationSpec struct {
|
type AuthenticationSpec struct {
|
||||||
Kopeio *KopeioAuthenticationSpec `json:"kopeio,omitempty"`
|
Kopeio *KopeioAuthenticationSpec `json:"kopeio,omitempty"`
|
||||||
|
Heptio *HeptioAuthenticationSpec `json:"heptio,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *AuthenticationSpec) IsEmpty() bool {
|
func (s *AuthenticationSpec) IsEmpty() bool {
|
||||||
return s.Kopeio == nil
|
return s.Kopeio == nil && s.Heptio == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type KopeioAuthenticationSpec struct {
|
type KopeioAuthenticationSpec struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HeptioAuthenticationSpec struct {
|
||||||
|
}
|
||||||
|
|
||||||
type AuthorizationSpec struct {
|
type AuthorizationSpec struct {
|
||||||
AlwaysAllow *AlwaysAllowAuthorizationSpec `json:"alwaysAllow,omitempty"`
|
AlwaysAllow *AlwaysAllowAuthorizationSpec `json:"alwaysAllow,omitempty"`
|
||||||
RBAC *RBACAuthorizationSpec `json:"rbac,omitempty"`
|
RBAC *RBACAuthorizationSpec `json:"rbac,omitempty"`
|
||||||
|
|
|
@ -229,15 +229,19 @@ type ExecContainerAction struct {
|
||||||
|
|
||||||
type AuthenticationSpec struct {
|
type AuthenticationSpec struct {
|
||||||
Kopeio *KopeioAuthenticationSpec `json:"kopeio,omitempty"`
|
Kopeio *KopeioAuthenticationSpec `json:"kopeio,omitempty"`
|
||||||
|
Heptio *HeptioAuthenticationSpec `json:"heptio,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *AuthenticationSpec) IsEmpty() bool {
|
func (s *AuthenticationSpec) IsEmpty() bool {
|
||||||
return s.Kopeio == nil
|
return s.Kopeio == nil && s.Heptio == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type KopeioAuthenticationSpec struct {
|
type KopeioAuthenticationSpec struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HeptioAuthenticationSpec struct {
|
||||||
|
}
|
||||||
|
|
||||||
type AuthorizationSpec struct {
|
type AuthorizationSpec struct {
|
||||||
AlwaysAllow *AlwaysAllowAuthorizationSpec `json:"alwaysAllow,omitempty"`
|
AlwaysAllow *AlwaysAllowAuthorizationSpec `json:"alwaysAllow,omitempty"`
|
||||||
RBAC *RBACAuthorizationSpec `json:"rbac,omitempty"`
|
RBAC *RBACAuthorizationSpec `json:"rbac,omitempty"`
|
||||||
|
|
|
@ -230,15 +230,19 @@ type ExecContainerAction struct {
|
||||||
|
|
||||||
type AuthenticationSpec struct {
|
type AuthenticationSpec struct {
|
||||||
Kopeio *KopeioAuthenticationSpec `json:"kopeio,omitempty"`
|
Kopeio *KopeioAuthenticationSpec `json:"kopeio,omitempty"`
|
||||||
|
Heptio *HeptioAuthenticationSpec `json:"heptio,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *AuthenticationSpec) IsEmpty() bool {
|
func (s *AuthenticationSpec) IsEmpty() bool {
|
||||||
return s.Kopeio == nil
|
return s.Kopeio == nil && s.Heptio == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type KopeioAuthenticationSpec struct {
|
type KopeioAuthenticationSpec struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HeptioAuthenticationSpec struct {
|
||||||
|
}
|
||||||
|
|
||||||
type AuthorizationSpec struct {
|
type AuthorizationSpec struct {
|
||||||
AlwaysAllow *AlwaysAllowAuthorizationSpec `json:"alwaysAllow,omitempty"`
|
AlwaysAllow *AlwaysAllowAuthorizationSpec `json:"alwaysAllow,omitempty"`
|
||||||
RBAC *RBACAuthorizationSpec `json:"rbac,omitempty"`
|
RBAC *RBACAuthorizationSpec `json:"rbac,omitempty"`
|
||||||
|
|
|
@ -260,6 +260,25 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
||||||
c.AddTask(t)
|
c.AddTask(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if b.Cluster.Spec.Authentication != nil {
|
||||||
|
if b.KopsModelContext.Cluster.Spec.Authentication.Heptio != nil {
|
||||||
|
alternateNames := []string{
|
||||||
|
"localhost",
|
||||||
|
"127.0.0.1",
|
||||||
|
}
|
||||||
|
|
||||||
|
t := &fitasks.Keypair{
|
||||||
|
Name: fi.String("heptio-authenticator-aws"),
|
||||||
|
Subject: "cn=heptio-authenticator-aws",
|
||||||
|
Type: "server",
|
||||||
|
AlternateNames: alternateNames,
|
||||||
|
Signer: defaultCA,
|
||||||
|
Format: format,
|
||||||
|
}
|
||||||
|
c.AddTask(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create auth tokens (though this is deprecated)
|
// Create auth tokens (though this is deprecated)
|
||||||
for _, x := range tokens.GetKubernetesAuthTokens_Deprecated() {
|
for _, x := range tokens.GetKubernetesAuthTokens_Deprecated() {
|
||||||
t := &fitasks.Secret{Name: fi.String(x), Lifecycle: b.Lifecycle}
|
t := &fitasks.Secret{Name: fi.String(x), Lifecycle: b.Lifecycle}
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
---
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: DaemonSet
|
||||||
|
metadata:
|
||||||
|
namespace: kube-system
|
||||||
|
name: heptio-authenticator-aws
|
||||||
|
labels:
|
||||||
|
k8s-app: heptio-authenticator-aws
|
||||||
|
spec:
|
||||||
|
updateStrategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
annotations:
|
||||||
|
scheduler.alpha.kubernetes.io/critical-pod: ""
|
||||||
|
labels:
|
||||||
|
k8s-app: heptio-authenticator-aws
|
||||||
|
spec:
|
||||||
|
# run on the host network (don't depend on CNI)
|
||||||
|
hostNetwork: true
|
||||||
|
|
||||||
|
# run on each master node
|
||||||
|
nodeSelector:
|
||||||
|
node-role.kubernetes.io/master: ""
|
||||||
|
tolerations:
|
||||||
|
- effect: NoSchedule
|
||||||
|
key: node-role.kubernetes.io/master
|
||||||
|
- key: CriticalAddonsOnly
|
||||||
|
operator: Exists
|
||||||
|
|
||||||
|
# run `heptio-authenticator-aws server` with three volumes
|
||||||
|
# - config (mounted from the ConfigMap at /etc/heptio-authenticator-aws/config.yaml)
|
||||||
|
# - state (persisted TLS certificate and keys, mounted from the host)
|
||||||
|
# - output (output kubeconfig to plug into your apiserver configuration, mounted from the host)
|
||||||
|
containers:
|
||||||
|
- name: heptio-authenticator-aws
|
||||||
|
image: gcr.io/heptio-images/authenticator:v0.1.0
|
||||||
|
args:
|
||||||
|
- server
|
||||||
|
- --config=/etc/heptio-authenticator-aws/config.yaml
|
||||||
|
- --state-dir=/var/heptio-authenticator-aws
|
||||||
|
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: 20Mi
|
||||||
|
cpu: 10m
|
||||||
|
limits:
|
||||||
|
memory: 20Mi
|
||||||
|
cpu: 100m
|
||||||
|
|
||||||
|
volumeMounts:
|
||||||
|
- name: config
|
||||||
|
mountPath: /etc/heptio-authenticator-aws/
|
||||||
|
- name: state
|
||||||
|
mountPath: /var/heptio-authenticator-aws/
|
||||||
|
- name: output
|
||||||
|
mountPath: /etc/kubernetes/heptio-authenticator-aws/
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: config
|
||||||
|
configMap:
|
||||||
|
name: heptio-authenticator-aws
|
||||||
|
- name: output
|
||||||
|
hostPath:
|
||||||
|
path: /srv/kubernetes/heptio-authenticator-aws/
|
||||||
|
- name: state
|
||||||
|
hostPath:
|
||||||
|
path: /srv/kubernetes/heptio-authenticator-aws/
|
|
@ -723,23 +723,44 @@ func (b *BootstrapChannelBuilder) buildManifest() (*channelsapi.Addons, map[stri
|
||||||
|
|
||||||
authenticationSelector := map[string]string{"role.kubernetes.io/authentication": "1"}
|
authenticationSelector := map[string]string{"role.kubernetes.io/authentication": "1"}
|
||||||
|
|
||||||
if b.cluster.Spec.Authentication != nil && b.cluster.Spec.Authentication.Kopeio != nil {
|
if b.cluster.Spec.Authentication != nil {
|
||||||
key := "authentication.kope.io"
|
if b.cluster.Spec.Authentication.Kopeio != nil {
|
||||||
version := "1.0.20171125"
|
key := "authentication.kope.io"
|
||||||
|
version := "1.0.20171125"
|
||||||
|
|
||||||
{
|
{
|
||||||
location := key + "/k8s-1.8.yaml"
|
location := key + "/k8s-1.8.yaml"
|
||||||
id := "k8s-1.8"
|
id := "k8s-1.8"
|
||||||
|
|
||||||
addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{
|
addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{
|
||||||
Name: fi.String(key),
|
Name: fi.String(key),
|
||||||
Version: fi.String(version),
|
Version: fi.String(version),
|
||||||
Selector: authenticationSelector,
|
Selector: authenticationSelector,
|
||||||
Manifest: fi.String(location),
|
Manifest: fi.String(location),
|
||||||
KubernetesVersion: ">=1.8.0",
|
KubernetesVersion: ">=1.8.0",
|
||||||
Id: id,
|
Id: id,
|
||||||
})
|
})
|
||||||
manifests[key+"-"+id] = "addons/" + location
|
manifests[key+"-"+id] = "addons/" + location
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if b.cluster.Spec.Authentication.Heptio != nil {
|
||||||
|
key := "authentication.hept.io"
|
||||||
|
version := "0.1.0"
|
||||||
|
|
||||||
|
{
|
||||||
|
location := key + "/k8s-1.10.yaml"
|
||||||
|
id := "k8s-1.10"
|
||||||
|
|
||||||
|
addons.Spec.Addons = append(addons.Spec.Addons, &channelsapi.AddonSpec{
|
||||||
|
Name: fi.String(key),
|
||||||
|
Version: fi.String(version),
|
||||||
|
Selector: authenticationSelector,
|
||||||
|
Manifest: fi.String(location),
|
||||||
|
KubernetesVersion: ">=1.10.0",
|
||||||
|
Id: id,
|
||||||
|
})
|
||||||
|
manifests[key+"-"+id] = "addons/" + location
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue