-
Notifications
You must be signed in to change notification settings - Fork 76
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bootstrap kubeconfig controller (#586)
* BootstrapKubeconfig CRD and Controller
- Loading branch information
Showing
30 changed files
with
798 additions
and
133 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// Copyright 2022 VMware, Inc. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package v1beta1 | ||
|
||
import ( | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
const ( | ||
// DefaultClusterName is the cluster name used in the generated bootstrap-kubeconfig | ||
DefaultClusterName = "default-cluster" | ||
|
||
// DefaultContext is the context name used in the generated bootstrap-kubeconfig | ||
DefaultContext = "default-context" | ||
|
||
// DefaultNamespace is the namespace used in the generated bootstrap-kubeconfig | ||
DefaultNamespace = "default" | ||
|
||
// DefaultAuth is the auth in the generated bootstrap-kubeconfig | ||
DefaultAuth = "default-auth" | ||
|
||
// BootstrapTokenDescription is the bootstrap token description for the secret that is generated | ||
BootstrapTokenDescription = "Token generated by cluster-api-provider-bringyourownhost" | ||
|
||
// BootstrapTokenExtraGroups is the byoh group that has access to create CertificateSigningRequest | ||
BootstrapTokenExtraGroups = "system:bootstrappers:byoh" | ||
) | ||
|
||
// BootstrapKubeconfigSpec defines the desired state of BootstrapKubeconfig | ||
type BootstrapKubeconfigSpec struct { | ||
// APIServer is the address of the kubernetes cluster (https://hostname:port). | ||
APIServer string `json:"apiserver"` | ||
|
||
// InsecureSkipTLSVerify skips the validity check for the server's certificate. This will make your HTTPS connections insecure. | ||
// +optional | ||
// +kubebuilder:default=false | ||
InsecureSkipTLSVerify bool `json:"insecure-skip-tls-verify,omitempty"` | ||
|
||
// CertificateAuthorityData contains PEM-encoded certificate authority certificates. | ||
CertificateAuthorityData string `json:"certificate-authority-data"` | ||
} | ||
|
||
// BootstrapKubeconfigStatus defines the observed state of BootstrapKubeconfig | ||
type BootstrapKubeconfigStatus struct { | ||
// BootstrapKubeconfigData is an optional reference to a bootstrap kubeconfig info | ||
// for starting the host registration process | ||
// +optional | ||
BootstrapKubeconfigData *string `json:"bootstrapKubeconfigData,omitempty"` | ||
} | ||
|
||
//+kubebuilder:object:root=true | ||
//+kubebuilder:subresource:status | ||
|
||
// BootstrapKubeconfig is the Schema for the bootstrapkubeconfigs API | ||
type BootstrapKubeconfig struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ObjectMeta `json:"metadata,omitempty"` | ||
|
||
Spec BootstrapKubeconfigSpec `json:"spec,omitempty"` | ||
Status BootstrapKubeconfigStatus `json:"status,omitempty"` | ||
} | ||
|
||
//+kubebuilder:object:root=true | ||
|
||
// BootstrapKubeconfigList contains a list of BootstrapKubeconfig | ||
type BootstrapKubeconfigList struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ListMeta `json:"metadata,omitempty"` | ||
Items []BootstrapKubeconfig `json:"items"` | ||
} | ||
|
||
func init() { | ||
SchemeBuilder.Register(&BootstrapKubeconfig{}, &BootstrapKubeconfigList{}) | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// Copyright 2022 VMware, Inc. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package bootstraptoken | ||
|
||
import ( | ||
"fmt" | ||
"time" | ||
|
||
infrastructurev1beta1 "github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/apis/infrastructure/v1beta1" | ||
v1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api" | ||
bootstrapapi "k8s.io/cluster-bootstrap/token/api" | ||
bootstraputil "k8s.io/cluster-bootstrap/token/util" | ||
) | ||
|
||
// GetTokenIDSecretFromBootstrapToken splits the token string and returns the tokenID and tokenSecret parts | ||
func GetTokenIDSecretFromBootstrapToken(tokenStr string) (tokenID, tokenSecret string, err error) { | ||
substrs := bootstraputil.BootstrapTokenRegexp.FindStringSubmatch(tokenStr) | ||
if len(substrs) != 3 { // nolint: gomnd | ||
return "", "", fmt.Errorf("the bootstrap token %q was not of the form %q", tokenStr, bootstrapapi.BootstrapTokenPattern) | ||
} | ||
|
||
return substrs[1], substrs[2], nil | ||
} | ||
|
||
// GenerateSecretFromBootstrapTokenStr builds the secret object from the token string | ||
// It also adds default description and auth groups that can be used by the bootstrap-kubeconfig | ||
func GenerateSecretFromBootstrapToken(tokenStr string, ttl time.Duration) (*v1.Secret, error) { | ||
tokenID, tokenSecret, err := GetTokenIDSecretFromBootstrapToken(tokenStr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
secretData := map[string][]byte{ | ||
bootstrapapi.BootstrapTokenIDKey: []byte(tokenID), | ||
bootstrapapi.BootstrapTokenSecretKey: []byte(tokenSecret), | ||
bootstrapapi.BootstrapTokenExpirationKey: []byte(time.Now().UTC().Add(ttl).Format(time.RFC3339)), | ||
bootstrapapi.BootstrapTokenUsageSigningKey: []byte("true"), | ||
bootstrapapi.BootstrapTokenUsageAuthentication: []byte("true"), | ||
bootstrapapi.BootstrapTokenDescriptionKey: []byte(infrastructurev1beta1.BootstrapTokenDescription), | ||
bootstrapapi.BootstrapTokenExtraGroupsKey: []byte(infrastructurev1beta1.BootstrapTokenExtraGroups), | ||
} | ||
|
||
bootstrapSecret := &v1.Secret{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: bootstraputil.BootstrapTokenSecretName(tokenID), | ||
Namespace: metav1.NamespaceSystem, | ||
}, | ||
Type: bootstrapapi.SecretTypeBootstrapToken, | ||
Data: secretData, | ||
} | ||
return bootstrapSecret, nil | ||
} | ||
|
||
// GenerateBootstrapKubeconfigFromBootstrapToken creates a bootstrap kubeconfig object from the bootstrap token generated | ||
// It also adds default cluster, context and auth info | ||
func GenerateBootstrapKubeconfigFromBootstrapToken(tokenStr string, bootstrapKubeconfig *infrastructurev1beta1.BootstrapKubeconfig) (*clientcmdapi.Config, error) { | ||
tokenID, tokenSecret, err := GetTokenIDSecretFromBootstrapToken(tokenStr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Build resulting kubeconfig. | ||
kubeconfigData := clientcmdapi.Config{ | ||
// Define a cluster stanza based on the bootstrap kubeconfig. | ||
Clusters: map[string]*clientcmdapi.Cluster{infrastructurev1beta1.DefaultClusterName: { | ||
Server: bootstrapKubeconfig.Spec.APIServer, | ||
InsecureSkipTLSVerify: bootstrapKubeconfig.Spec.InsecureSkipTLSVerify, | ||
CertificateAuthorityData: []byte(bootstrapKubeconfig.Spec.CertificateAuthorityData), | ||
}}, | ||
// Define auth based on the obtained client cert. | ||
AuthInfos: map[string]*clientcmdapi.AuthInfo{infrastructurev1beta1.DefaultAuth: { | ||
Token: fmt.Sprintf(tokenID + "." + tokenSecret), | ||
}}, | ||
// Define a context that connects the auth info and cluster, and set it as the default | ||
Contexts: map[string]*clientcmdapi.Context{infrastructurev1beta1.DefaultContext: { | ||
Cluster: infrastructurev1beta1.DefaultClusterName, | ||
AuthInfo: infrastructurev1beta1.DefaultAuth, | ||
Namespace: infrastructurev1beta1.DefaultNamespace, | ||
}}, | ||
CurrentContext: infrastructurev1beta1.DefaultContext, | ||
} | ||
|
||
return &kubeconfigData, nil | ||
} |
74 changes: 74 additions & 0 deletions
74
config/crd/bases/infrastructure.cluster.x-k8s.io_bootstrapkubeconfigs.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
|
||
--- | ||
apiVersion: apiextensions.k8s.io/v1 | ||
kind: CustomResourceDefinition | ||
metadata: | ||
annotations: | ||
controller-gen.kubebuilder.io/version: v0.4.1 | ||
creationTimestamp: null | ||
name: bootstrapkubeconfigs.infrastructure.cluster.x-k8s.io | ||
spec: | ||
group: infrastructure.cluster.x-k8s.io | ||
names: | ||
kind: BootstrapKubeconfig | ||
listKind: BootstrapKubeconfigList | ||
plural: bootstrapkubeconfigs | ||
singular: bootstrapkubeconfig | ||
scope: Namespaced | ||
versions: | ||
- name: v1beta1 | ||
schema: | ||
openAPIV3Schema: | ||
description: BootstrapKubeconfig is the Schema for the bootstrapkubeconfigs | ||
API | ||
properties: | ||
apiVersion: | ||
description: 'APIVersion defines the versioned schema of this representation | ||
of an object. Servers should convert recognized schemas to the latest | ||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' | ||
type: string | ||
kind: | ||
description: 'Kind is a string value representing the REST resource this | ||
object represents. Servers may infer this from the endpoint the client | ||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' | ||
type: string | ||
metadata: | ||
type: object | ||
spec: | ||
description: BootstrapKubeconfigSpec defines the desired state of BootstrapKubeconfig | ||
properties: | ||
apiserver: | ||
description: APIServer is the address of the kubernetes cluster (https://hostname:port). | ||
type: string | ||
certificate-authority-data: | ||
description: CertificateAuthorityData contains PEM-encoded certificate | ||
authority certificates. | ||
type: string | ||
insecure-skip-tls-verify: | ||
default: false | ||
description: InsecureSkipTLSVerify skips the validity check for the | ||
server's certificate. This will make your HTTPS connections insecure. | ||
type: boolean | ||
required: | ||
- apiserver | ||
- certificate-authority-data | ||
type: object | ||
status: | ||
description: BootstrapKubeconfigStatus defines the observed state of BootstrapKubeconfig | ||
properties: | ||
bootstrapKubeconfigData: | ||
description: BootstrapKubeconfigData is an optional reference to a | ||
bootstrap kubeconfig info for starting the host registration process | ||
type: string | ||
type: object | ||
type: object | ||
served: true | ||
storage: true | ||
subresources: | ||
status: {} | ||
status: | ||
acceptedNames: | ||
kind: "" | ||
plural: "" | ||
conditions: [] | ||
storedVersions: [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
config/crd/patches/cainjection_in_infrastructure_bootstrapkubeconfigs.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# The following patch adds a directive for certmanager to inject CA into the CRD | ||
apiVersion: apiextensions.k8s.io/v1 | ||
kind: CustomResourceDefinition | ||
metadata: | ||
annotations: | ||
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) | ||
name: bootstrapkubeconfigs.infrastructure.cluster.x-k8s.io |
Oops, something went wrong.