Skip to content

Commit

Permalink
Merge pull request #12 from packethost/ca-as-secret
Browse files Browse the repository at this point in the history
save CA as secret
  • Loading branch information
deitch authored Mar 19, 2020
2 parents 3b0a175 + 408d411 commit b6705a6
Show file tree
Hide file tree
Showing 57 changed files with 405 additions and 10,909 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ endif
$(GO) run -mod=vendor vendor/sigs.k8s.io/controller-tools/cmd/controller-gen/main.go all
# patch the particular image tag we will want to deploy
@echo "updating kustomize image patch file for manager resource"
sed -i'' -e 's@PATCH_ME_IMAGE@image: '"$(PATCH_IMAGE_TAG)"'@' ./config/default/manager_image_patch.yaml
sed -i'' -e 's@PATCH_ME_IMAGE@'"$(PATCH_IMAGE_TAG)"'@' ./config/default/manager_image_patch.yaml
# create the manifests
$(KUBECTL) kustomize vendor/sigs.k8s.io/cluster-api/config/default/ > $(PROVIDERYAML)
echo "---" >> $(PROVIDERYAML)
Expand Down
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ To use the cluster-api to deploy a Kubernetes cluster to Packet, you need the fo
* A Packet API key
* A Packet project ID
* The `clusterctl` binary from this repository.
* A Kubernetes cluster - the "bootstrap cluster" - that will deploy and manage the cluster on Packet.
* A Kubernetes cluster - the "bootstrap cluster" - that will deploy and manage the cluster on Packet.
* `kubectl` - not absolutely required, but hard to interact with a cluster without it

For the bootstrap cluster, any cluster is just fine for this, including [k3s](https://k3s.io), [k3d](https://github.com/rancher/k3d) and [kind](https://github.com/kubernetes-sigs/kind).
Expand All @@ -34,13 +34,15 @@ To deploy a cluster:
* `CLUSTER_NAME` - The created cluster will have this name. If not set, it will generate one for you.
* `FACILITY` - The Packet facility where you wantto deploy the cluster. If not set, it will default to `ewr1`.
* `SSH_KEY` - The path to an ssh public key to place on all of the machines. If not set, it will use whichever ssh keys are defined for your project.
* `CA_KEY` - The path to a file with the CA private key. If not set, it will generate one for you.
* `CA_CERT` - The path to a file with the CA certificate. If not set, it will generate one for you.
1. Create the config files you need via `./generate-yaml.sh`. This will generate the following files in [out/packet](./out/packet):
* `cluster.yaml`
* `machines.yaml`
* `provider-components.yaml` - note that this file _will_ contain your secrets, specifically `PACKET_API_KEY`, to be loaded into the cluster
* `provider-components.yaml` - note that this file _will_ contain your secrets, specifically `PACKET_API_KEY`, to be loaded into the cluster, and optionally your CA private key, if provided (but not if auto-generated)
* `addons.yaml` - note that this file _will_ contain your secrets, specifically `PACKET_API_KEY`, to be loaded into the cluster
1. If desired, edit the following files:
* `cluster.yaml` - to change parameters or settings, including network CIDRs, and, if desired, your own CA certificate and key
* `cluster.yaml` - to change parameters or settings, including network CIDRs
* `machines.yaml` - to change parameters or settings, including machine types and quantity
1. Run `clusterctl` with the appropriate command.

Expand Down Expand Up @@ -72,7 +74,6 @@ Run `clusterctl create cluster --help` for more options, for example to use an e

If you do not change the generated `yaml` files, it will use defaults. You can look in the `*.yaml.template` files in [cmd/clusterctl/examples/packet/](./cmd/clusterctl/examples/packet/) for details.

* CA key/certificate: leave blank, which will cause the `manager` to create one.
* service CIDR: `172.25.0.0/16`
* pod CIDR: `172.26.0.0/16`
* service domain: `cluster.local`
Expand Down Expand Up @@ -112,7 +113,7 @@ Note that, unlike `clusterctl`, this method will not take care of the following:

The components deployed via the `yaml` files are the following:

* `cluster.yaml` - contains
* `cluster.yaml` - contains
* a single `Cluster` CRD which defines the new cluster to be deployed. Includes cluster-wide definitions, including cidr definitions for services and pods.
* `machines.yaml` - contains
* one or more `Machine` CRDs, which cause the deployment of individual server instance to serve as Kubernetes master or worker nodes.
Expand Down Expand Up @@ -142,9 +143,9 @@ The Packet cluster-api provider follows the standard design for cluster-api. It
The actual machines are deployed using `kubeadm`. The deployment process uses the following process.

1. When a new `Cluster` is created:
* if the `ClusterSpec` does not include a CA key/certificate pair, create one and save it on the `Cluster` object
* if the appropriate `Secret` does not include a CA key/certificate pair, create one and save it in that `Secret`
2. When a new master `Machine` is created:
* retrieve the CA certificate and key from the `Cluster` object
* retrieve the CA certificate and key from the appropriate Kubernetes `Secret`
* launch a new server instance on Packet
* set the `cloud-init` on the instance to run `kubeadm init`, passing it the CA certificate and key
3. When a new worker `Machine` is created:
Expand Down Expand Up @@ -265,5 +266,3 @@ Important notes:
## References

* [kubeadm yaml api](https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2)


22 changes: 19 additions & 3 deletions cmd/clusterctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,20 @@ import (
"github.com/packethost/cluster-api-provider-packet/pkg/cloud/packet"
"github.com/packethost/cluster-api-provider-packet/pkg/cloud/packet/deployer"
"github.com/packethost/cluster-api-provider-packet/pkg/cloud/packet/util"
kclient "k8s.io/client-go/kubernetes"
clientv1 "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/klog"
"sigs.k8s.io/cluster-api/cmd/clusterctl/cmd"
"sigs.k8s.io/cluster-api/pkg/apis/cluster/common"
"sigs.k8s.io/controller-runtime/pkg/client/config"
)

func main() {
var err error
var (
err error
kube *kclient.Clientset
secretsGetter clientv1.SecretsGetter
)

flag.Parse()

Expand All @@ -38,10 +45,19 @@ func main() {
klog.Fatalf("unable to get Packet client: %v", err)
}

cfg, _ := config.GetConfig()
if cfg != nil {
kube, _ = kclient.NewForConfig(cfg)
}
if kube != nil {
secretsGetter = kube.CoreV1()
}

// get a deployer, which is needed at various stages
deployer, err := deployer.New(deployer.Params{
Port: util.ControlPort,
Client: client,
Port: util.ControlPort,
SecretsGetter: secretsGetter,
Client: client,
})
if err != nil {
klog.Fatalf("unable to get deployer: %v", err)
Expand Down
12 changes: 10 additions & 2 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/packethost/cluster-api-provider-packet/pkg/cloud/packet/actuators/machine/machineconfig"
"github.com/packethost/cluster-api-provider-packet/pkg/cloud/packet/deployer"
"github.com/packethost/cluster-api-provider-packet/pkg/cloud/packet/util"
kclient "k8s.io/client-go/kubernetes"
"k8s.io/klog"
clusterapis "sigs.k8s.io/cluster-api/pkg/apis"
"sigs.k8s.io/cluster-api/pkg/apis/cluster/common"
Expand Down Expand Up @@ -67,6 +68,10 @@ func main() {
if err != nil {
klog.Fatalf(err.Error())
}
kube, err := kclient.NewForConfig(cfg)
if err != nil {
klog.Fatalf(err.Error())
}

// get a packet client
client, err := packet.GetClient()
Expand All @@ -75,8 +80,9 @@ func main() {
}
// get a deployer, which is needed at various stages
deployer, err := deployer.New(deployer.Params{
Client: client,
Port: util.ControlPort,
Client: client,
SecretsGetter: kube.CoreV1(),
Port: util.ControlPort,
})
if err != nil {
klog.Fatalf(err.Error())
Expand All @@ -85,6 +91,7 @@ func main() {
clusterInterface := cs.ClusterV1alpha1()
clusterActuator, err := cluster.NewActuator(cluster.ActuatorParams{
ClustersGetter: clusterInterface,
SecretsGetter: kube.CoreV1(),
Deployer: deployer,
})
if err != nil {
Expand All @@ -100,6 +107,7 @@ func main() {
machineActuator, err := machine.NewActuator(machine.ActuatorParams{
MachinesGetter: clusterInterface,
MachineConfigGetter: getter,
SecretsGetter: kube.CoreV1(),
Client: client,
Deployer: deployer,
})
Expand Down
14 changes: 0 additions & 14 deletions config/crds/packetprovider_v1alpha1_packetclusterproviderspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,6 @@ spec:
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/api-conventions.md#resources'
type: string
caKeyPair:
description: CAKeyPair is the key pair for ca certs.
properties:
cert:
description: base64 encoded cert and key
format: byte
type: string
key:
format: byte
type: string
required:
- cert
- key
type: object
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
Expand Down
2 changes: 2 additions & 0 deletions config/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Adds namespace to all resources.
# This must match PRECISELY what is in the constant in pkg/cloud/packet/util.CAPPNamespace
namespace: cluster-api-provider-packet-system

# Value of this field is prepended to the
# names of all resources, e.g. a deployment named
# "wordpress" becomes "alices-wordpress".
# Note that it should also match with the prefix (text before '-') of the namespace
# field above.
# This must match PRECISELY what is in the constant in pkg/cloud/packet/util.CAPPPrefix
namePrefix: cluster-api-provider-packet-

bases:
Expand Down
10 changes: 10 additions & 0 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,13 @@ stringData:
apiKey: $PACKET_API_KEY
projectID: $PACKET_PROJECT_ID
type: Opaque
---
apiVersion: v1
kind: Secret
metadata:
name: ca-$CLUSTER_NAME
namespace: system
stringData:
key: $CA_KEY
certificate: $CA_CERT
type: Opaque
32 changes: 30 additions & 2 deletions generate-yaml.sh
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ if [ -z "$PACKET_API_KEY" ]; then
exit 1
fi


mkdir -p ${OUTPUT_DIR}

SSH_KEY=${SSH_KEY:-}
Expand All @@ -141,13 +140,42 @@ else
SSH_KEY=$SSH_PUBLIC_FILE
fi

CA_KEY="${CA_KEY:-}"
CA_CERT="${CA_CERT:-}"
CA_KEY_CONTENT=
CA_CERT_CONTENT=
if [ -z "$CA_KEY" -o -z "$CA_CERT" ]; then
echo "CA key and CA certificate not provided, will generate automatically"
elif [ ! -e "$CA_KEY" ]; then
echo "CA private key file $CA_KEY does not exist" >&2
exit 1
elif [ ! -e "$CA_CERT" ]; then
echo "CA certificate file $CA_CERT does not exist" >&2
exit 1
else
CA_KEY_CONTENT=$(cat $CA_KEY | base64 | tr -d '\r\n')
CA_CERT_CONTENT=$(cat $CA_CERT | base64 | tr -d '\r\n')
fi
# to be sane about the output
if [ -z "$CA_KEY_CONTENT" ]; then
CA_KEY_CONTENT="''"
fi
if [ -z "$CA_CERT_CONTENT" ]; then
CA_CERT_CONTENT="''"
fi



# By default, linux wraps base64 output every 76 cols, so we use 'tr -d' to remove whitespaces.
# Note 'base64 -w0' doesn't work on Mac OS X, which has different flags.
SSH_PUBLIC=$(cat $SSH_KEY | base64 | tr -d '\r\n')

cat $PROVIDER_TEMPLATE_FILE \
| sed -e "s/\$CLUSTER_NAME/$CLUSTER_NAME/" \
| sed -e "s/\$PACKET_PROJECT_ID/$PACKET_PROJECT_ID/" \
| sed -e "s/\$PACKET_API_KEY/$PACKET_API_KEY/" > $PROVIDER_GENERATED_FILE
| sed -e "s/\$PACKET_API_KEY/$PACKET_API_KEY/" \
| sed -e "s/\$CA_KEY/$CA_KEY_CONTENT/" \
| sed -e "s/\$CA_CERT/$CA_CERT_CONTENT/" > $PROVIDER_GENERATED_FILE

cat $MACHINE_TEMPLATE_FILE \
| sed -e "s/\$CLUSTER_NAME/$CLUSTER_NAME/" \
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ require (
go.uber.org/zap v1.10.0 // indirect
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect

k8s.io/api v0.0.0-20190222213804-5cb15d344471
k8s.io/apimachinery v0.0.0-20190703205208-4cfb76a8bf76
k8s.io/client-go v10.0.0+incompatible
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,6 @@ type PacketClusterProviderSpec struct {
metav1.ObjectMeta `json:"metadata,omitempty"`

ProjectID string `json:"projectID"`

// CAKeyPair is the key pair for ca certs.
CAKeyPair KeyPair `json:"caKeyPair,omitempty"`
}

// KeyPair is how operators can supply custom keypairs for kubeadm to use.
type KeyPair struct {
// base64 encoded cert and key
Cert []byte `json:"cert"`
Key []byte `json:"key"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ func TestStoragePacketClusterProviderSpec(t *testing.T) {
Name: "foo",
Namespace: "default",
},
CAKeyPair: KeyPair{
Key: []byte{10, 20, 30},
Cert: []byte{10, 20, 30},
},
}
g := gomega.NewGomegaWithT(t)

Expand Down
27 changes: 0 additions & 27 deletions pkg/apis/packetprovider/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit b6705a6

Please sign in to comment.