Skip to content

Commit

Permalink
Enable Fleet Workload ID pools (#164)
Browse files Browse the repository at this point in the history
* Added ASM resource label logic to the cluster module

* Added ASM resource label logic to the cluster module

* Added ASM resource label logic to the cluster module

* Added Authority to cluster config.

* added issuer version

* Added both versions of the gateway crds

* Cleaned up unused code in the CLI

* Added tracing to ASM config map

Co-authored-by: Nick Eberts <[email protected]>
  • Loading branch information
knee-berts and knee-berts authored May 6, 2022
1 parent 37fad2b commit 1680afb
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 238 deletions.
16 changes: 0 additions & 16 deletions cli/cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,22 +76,6 @@ var createCmd = &cobra.Command{
log.Info("✅ Clusters API access check passed.")
}

// Init Multi-cluster Gateway
// if conf.MultiClusterGateway {
// err := anthos.InitMCG(kc)
// if err != nil {
// log.Errorf("🚨 Failed to initialize Multi-cluster Gateway CRDs: %s", err)
// } else {
// log.Info("✅ MultiCluster Gateway CRDs installed successfully.")
// }
// }

// Run Anthos modules if anthos features are enabled
// if conf.ConfigSync || conf.MultiClusterGateway {
// lifecycle.InitTF("anthos", tfStateBucket[2])
// lifecycle.ApplyTF("anthos")
// }

// Init ACM (either ConfigSync or ConfigSync plus PolicyController)
if conf.ConfigSync {
err := anthos.InitACM(conf, kc)
Expand Down
240 changes: 111 additions & 129 deletions cli/pkg/anthos/configsync.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,11 @@ limitations under the License.
package anthos

import (
"context"
"fmt"
"io/ioutil"
"strings"

"gkekitctl/pkg/config"

log "github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // register GCP auth provider
"k8s.io/client-go/tools/clientcmd/api"

"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"os"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/clientcmd"

"golang.org/x/crypto/ssh"
)

// If ConfigSync is enabled, this function runs after TF apply and does the following:
Expand All @@ -60,121 +42,121 @@ func InitACM(conf *config.Config, kc *api.Config) error {
log.Infof("✔️ Kubeconfig generated: %+v", kc)

// Verify access to Kubernetes API on all clusters
log.Info("☸️ Verifying Kubernetes API access for all clusters...")
err = ListNamespaces(kc)
if err != nil {
return err
}
// log.Info("☸️ Verifying Kubernetes API access for all clusters...")
// err = ListNamespaces(kc)
// if err != nil {
// return err
// }
return nil
}

// ssh-keygen
// Source: https://stackoverflow.com/questions/21151714/go-generate-an-ssh-public-key
func InitSSH() error {
privateKeyPath := "id_rsa"
pubKeyPath := "id_rsa.pub"

// make ssh dir if not exists
err := os.MkdirAll("ssh", 0700)
if err != nil {
log.Warnf("Error making ssh dir: %v", err)
}

// ssh keygen to local dir
log.Info("Generating private key")
privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return err
}

// generate and write private key as PEM
log.Info("Encoding private key")
privateKeyFile, err := os.Create(privateKeyPath)
defer privateKeyFile.Close()
if err != nil {
return err
}
privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}
if err := pem.Encode(privateKeyFile, privateKeyPEM); err != nil {
return err
}

// generate and write public key
log.Info("Generating public key")
pub, err := ssh.NewPublicKey(&privateKey.PublicKey)
if err != nil {
return err
}
return ioutil.WriteFile(pubKeyPath, ssh.MarshalAuthorizedKey(pub), 0655)
}

func PromptUser(conf *config.Config) error {
// read public key as string
bytes, err := ioutil.ReadFile("id_rsa.pub")
if err != nil {
return err
}
pubKey := string(bytes)

// Prompt user to register ssh public key to their Cloud Source Repositories
log.Info("💻 Copy the key below to the clipboard, then open this link to register: https://source.cloud.google.com/user/ssh_keys")
log.Info(pubKey)
log.Info("Once you've registered the key, press enter to continue...")
fmt.Scanln() // wait for Enter Key

// Prompt user to run make start proxy
if conf.PrivateEndpoint {
log.Info("⚠️ Your clusters have Private Endpoints. Please open another terminal tab and run the following command to proxy via your GCE Bastion Host.")
log.Infof("gcloud beta compute ssh gke-tk-bastion --tunnel-through-iap --project %s --zone %s-b -- -4 -L8888:127.0.0.1:8888", conf.ClustersProjectID, conf.ClustersConfig[0].Region)
log.Info("Once the proxy tunnel is running, press enter to continue...")
fmt.Scanln() // wait for Enter Key
}
return nil
}
// func InitSSH() error {
// privateKeyPath := "id_rsa"
// pubKeyPath := "id_rsa.pub"

// // make ssh dir if not exists
// err := os.MkdirAll("ssh", 0700)
// if err != nil {
// log.Warnf("Error making ssh dir: %v", err)
// }

// // ssh keygen to local dir
// log.Info("Generating private key")
// privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
// if err != nil {
// return err
// }

// // generate and write private key as PEM
// log.Info("Encoding private key")
// privateKeyFile, err := os.Create(privateKeyPath)
// defer privateKeyFile.Close()
// if err != nil {
// return err
// }
// privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}
// if err := pem.Encode(privateKeyFile, privateKeyPEM); err != nil {
// return err
// }

// // generate and write public key
// log.Info("Generating public key")
// pub, err := ssh.NewPublicKey(&privateKey.PublicKey)
// if err != nil {
// return err
// }
// return ioutil.WriteFile(pubKeyPath, ssh.MarshalAuthorizedKey(pub), 0655)
// }

// func PromptUser(conf *config.Config) error {
// // read public key as string
// bytes, err := ioutil.ReadFile("id_rsa.pub")
// if err != nil {
// return err
// }
// pubKey := string(bytes)

// // Prompt user to register ssh public key to their Cloud Source Repositories
// log.Info("💻 Copy the key below to the clipboard, then open this link to register: https://source.cloud.google.com/user/ssh_keys")
// log.Info(pubKey)
// log.Info("Once you've registered the key, press enter to continue...")
// fmt.Scanln() // wait for Enter Key

// // Prompt user to run make start proxy
// if conf.PrivateEndpoint {
// log.Info("⚠️ Your clusters have Private Endpoints. Please open another terminal tab and run the following command to proxy via your GCE Bastion Host.")
// log.Infof("gcloud beta compute ssh gke-tk-bastion --tunnel-through-iap --project %s --zone %s-b -- -4 -L8888:127.0.0.1:8888", conf.ClustersProjectID, conf.ClustersConfig[0].Region)
// log.Info("Once the proxy tunnel is running, press enter to continue...")
// fmt.Scanln() // wait for Enter Key
// }
// return nil
// }

// Create gitcreds Secret in every cluster, using the contents of the id_rsa file as data.
func CreateGitCredsSecret(kubeConfig *api.Config) error {
ctx := context.Background()

// Get string value of private key
privateKey, err := ioutil.ReadFile("id_rsa")
if err != nil {
return fmt.Errorf("Failed to read id_rsa from file: %v", err)
}
privateKeyString := string(privateKey)
// log.Infof("Private key string is the contents below:")
// log.Info(privateKeyString)

for clusterName := range kubeConfig.Clusters {
cfg, err := clientcmd.NewNonInteractiveClientConfig(*kubeConfig, clusterName, &clientcmd.ConfigOverrides{CurrentContext: clusterName}, nil).ClientConfig()
if err != nil {
return fmt.Errorf("failed to create Kubernetes configuration cluster=%s: %w", clusterName, err)
}

k8s, err := kubernetes.NewForConfig(cfg)
if err != nil {
return fmt.Errorf("failed to create Kubernetes client cluster=%s: %w", clusterName, err)
}

err = WaitForNamespace(k8s, ctx, "config-management-system", clusterName)
if err != nil {
return fmt.Errorf("config management system namespace is not ready on cluster=%s: %w", clusterName, err)
}

_, err = k8s.CoreV1().Secrets("config-management-system").Create(ctx, &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "git-creds",
},
StringData: map[string]string{"ssh": privateKeyString},
}, metav1.CreateOptions{})

if err != nil {
if strings.Contains(err.Error(), "already exists") {
log.Warn("git-creds secret already exists")
} else {
return fmt.Errorf("failed to create gitcreds secret- cluster=%s: %w", clusterName, err)
}
}
}
return nil
}
// func CreateGitCredsSecret(kubeConfig *api.Config) error {
// ctx := context.Background()

// // Get string value of private key
// privateKey, err := ioutil.ReadFile("id_rsa")
// if err != nil {
// return fmt.Errorf("Failed to read id_rsa from file: %v", err)
// }
// privateKeyString := string(privateKey)
// // log.Infof("Private key string is the contents below:")
// // log.Info(privateKeyString)

// for clusterName := range kubeConfig.Clusters {
// cfg, err := clientcmd.NewNonInteractiveClientConfig(*kubeConfig, clusterName, &clientcmd.ConfigOverrides{CurrentContext: clusterName}, nil).ClientConfig()
// if err != nil {
// return fmt.Errorf("failed to create Kubernetes configuration cluster=%s: %w", clusterName, err)
// }

// k8s, err := kubernetes.NewForConfig(cfg)
// if err != nil {
// return fmt.Errorf("failed to create Kubernetes client cluster=%s: %w", clusterName, err)
// }

// err = WaitForNamespace(k8s, ctx, "config-management-system", clusterName)
// if err != nil {
// return fmt.Errorf("config management system namespace is not ready on cluster=%s: %w", clusterName, err)
// }

// _, err = k8s.CoreV1().Secrets("config-management-system").Create(ctx, &v1.Secret{
// ObjectMeta: metav1.ObjectMeta{
// Name: "git-creds",
// },
// StringData: map[string]string{"ssh": privateKeyString},
// }, metav1.CreateOptions{})

// if err != nil {
// if strings.Contains(err.Error(), "already exists") {
// log.Warn("git-creds secret already exists")
// } else {
// return fmt.Errorf("failed to create gitcreds secret- cluster=%s: %w", clusterName, err)
// }
// }
// }
// return nil
// }
85 changes: 40 additions & 45 deletions cli/pkg/anthos/kubernetes_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,11 @@ import (
"fmt"
"gkekitctl/pkg/config"

"github.com/pytimer/k8sutil/apply"
log "github.com/sirupsen/logrus"
"google.golang.org/api/container/v1"
clientgo "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/discovery"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/clientcmd/api"
)
Expand Down Expand Up @@ -95,10 +90,10 @@ func GenerateKubeConfig(conf *config.Config) (*api.Config, error) {
}

// Write kubeconfig to YAML file
err = clientcmd.WriteToFile(ret, "kubeconfig")
if err != nil {
return &ret, err
}
// err = clientcmd.WriteToFile(ret, "kubeconfig")
// if err != nil {
// return &ret, err
// }
return &ret, nil
}

Expand Down Expand Up @@ -131,44 +126,44 @@ func ListNamespaces(kubeConfig *api.Config) error {
}

// Kubectl apply using client.go
func Apply(config *rest.Config, clusterName string, fileName []byte) error {
// func Apply(config *rest.Config, clusterName string, fileName []byte) error {

dynamicClient, err := dynamic.NewForConfig(config)
if err != nil {
return fmt.Errorf("failed to setup dynamic client for cluster=%s: %w", clusterName, err)
}
discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
if err != nil {
return fmt.Errorf("failed to setup diecovery client for cluster=%s: %w", clusterName, err)
}
// dynamicClient, err := dynamic.NewForConfig(config)
// if err != nil {
// return fmt.Errorf("failed to setup dynamic client for cluster=%s: %w", clusterName, err)
// }
// discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
// if err != nil {
// return fmt.Errorf("failed to setup diecovery client for cluster=%s: %w", clusterName, err)
// }

applyOptions := apply.NewApplyOptions(dynamicClient, discoveryClient)
if err := applyOptions.Apply(context.TODO(), fileName); err != nil {
return fmt.Errorf("failed to create apply gateway crd cluster=%s: %w", clusterName, err)
}
// applyOptions := apply.NewApplyOptions(dynamicClient, discoveryClient)
// if err := applyOptions.Apply(context.TODO(), fileName); err != nil {
// return fmt.Errorf("failed to create apply gateway crd cluster=%s: %w", clusterName, err)
// }

return nil
}
// return nil
// }

// check namespace and watch if not created
func WaitForNamespace(k8s *kubernetes.Clientset, ctx context.Context, nameSpace string, clusterName string) error {
ns, err := k8s.CoreV1().Namespaces().Get(ctx, "config-management-system", metav1.GetOptions{})
timeout := int64(120)
if clientgo.IsNotFound(err) {
log.Infof("%s was not found on cluster=%s: %v", nameSpace, clusterName, err)
ns, err := k8s.CoreV1().Namespaces().Watch(ctx, metav1.ListOptions{
FieldSelector: "metadata.name=" + nameSpace,
Watch: true,
TimeoutSeconds: &timeout,
})
if err != nil {
return fmt.Errorf("failed watch on namespace %s on cluster=%s: %v", nameSpace, clusterName, err)
}
log.Infof("%s is ready on cluster: %s", ns, clusterName)

} else if err != nil {
return fmt.Errorf("%s namespace on cluster=%s: %w", nameSpace, clusterName, err)
}
log.Infof("%s is ready on cluster: %s", ns, clusterName)
return nil
}
// func WaitForNamespace(k8s *kubernetes.Clientset, ctx context.Context, nameSpace string, clusterName string) error {
// ns, err := k8s.CoreV1().Namespaces().Get(ctx, "config-management-system", metav1.GetOptions{})
// timeout := int64(120)
// if clientgo.IsNotFound(err) {
// log.Infof("%s was not found on cluster=%s: %v", nameSpace, clusterName, err)
// ns, err := k8s.CoreV1().Namespaces().Watch(ctx, metav1.ListOptions{
// FieldSelector: "metadata.name=" + nameSpace,
// Watch: true,
// TimeoutSeconds: &timeout,
// })
// if err != nil {
// return fmt.Errorf("failed watch on namespace %s on cluster=%s: %v", nameSpace, clusterName, err)
// }
// log.Infof("%s is ready on cluster: %s", ns, clusterName)

// } else if err != nil {
// return fmt.Errorf("%s namespace on cluster=%s: %w", nameSpace, clusterName, err)
// }
// log.Infof("%s is ready on cluster: %s", ns, clusterName)
// return nil
// }
Loading

0 comments on commit 1680afb

Please sign in to comment.