8 Commits

Author SHA1 Message Date
Dalton Hubble
2c04ea46ee CHANGES.md: Prepare for a v0.6.1 docs point release 2017-05-25 10:33:04 -07:00
Dalton Hubble
317307f6f6 glide.yaml: Update and vendor the crypto openpgp package 2017-05-25 10:32:42 -07:00
Dalton Hubble
3d30cff9ec travis.yml: Use Go 1.8.3 in tests and published images 2017-05-25 10:32:42 -07:00
Dalton Hubble
15a1128398 scripts: Move examples/etc/matchbox to scripts/tls
* Use the same TLS cert-gen location in source as in releases
2017-05-25 10:32:42 -07:00
Dalton Hubble
1b7f60b895 scripts: Move development-only scripts under scripts/dev 2017-05-25 10:32:42 -07:00
Dalton Hubble
26a901ecd6 examples/terraform: Add tfvars showing multi-controller case 2017-05-25 10:32:42 -07:00
enilfodne
19a402c187 examples: Bump Container Linux version to stable 1353.7.0 2017-05-25 10:32:42 -07:00
Dalton Hubble
02f7fb7f7c scripts: Remove unused static k8s generation scripts
* Remove static rktnetes cluster docs
* Bump devnet matchbox version
2017-05-25 10:32:42 -07:00
64 changed files with 345 additions and 452 deletions

View File

@@ -4,7 +4,7 @@ services:
- docker
go:
- 1.7.4
- 1.8
- 1.8.3
- tip
matrix:
allow_failures:
@@ -15,10 +15,10 @@ script:
- make test
deploy:
provider: script
script: scripts/travis-docker-push
script: scripts/dev/travis-docker-push
skip_cleanup: true
on:
branch: master
go: '1.8'
go: '1.8.3'
notifications:
email: change

View File

@@ -4,6 +4,14 @@ Notable changes between releases.
## Latest
* Remove pixiecore support (deprecated in v0.5.0)
## v0.6.1 (2017-05-25)
* Improve the installation documentation
* Move examples/etc/matchbox/cert-gen to scripts/tls
* Build Matchbox with Go 1.8.3 for images and binaries
### Examples
* Upgrade self-hosted Kubernetes cluster examples to v1.6.4

View File

@@ -39,8 +39,8 @@ GET http://matchbox.foo/ipxe?label=value
```
#!ipxe
kernel /assets/coreos/1298.7.0/coreos_production_pxe.vmlinuz coreos.config.url=http://matchbox.foo:8080/ignition?uuid=${uuid}&mac=${mac:hexhyp} coreos.first_boot=1 coreos.autologin
initrd /assets/coreos/1298.7.0/coreos_production_pxe_image.cpio.gz
kernel /assets/coreos/1353.7.0/coreos_production_pxe.vmlinuz coreos.config.url=http://matchbox.foo:8080/ignition?uuid=${uuid}&mac=${mac:hexhyp} coreos.first_boot=1 coreos.autologin
initrd /assets/coreos/1353.7.0/coreos_production_pxe_image.cpio.gz
boot
```
@@ -67,9 +67,9 @@ default=0
timeout=1
menuentry "CoreOS" {
echo "Loading kernel"
linuxefi "(http;matchbox.foo:8080)/assets/coreos/1298.7.0/coreos_production_pxe.vmlinuz" "coreos.autologin" "coreos.config.url=http://matchbox.foo:8080/ignition" "coreos.first_boot"
linuxefi "(http;matchbox.foo:8080)/assets/coreos/1353.7.0/coreos_production_pxe.vmlinuz" "coreos.autologin" "coreos.config.url=http://matchbox.foo:8080/ignition" "coreos.first_boot"
echo "Loading initrd"
initrdefi "(http;matchbox.foo:8080)/assets/coreos/1298.7.0/coreos_production_pxe_image.cpio.gz"
initrdefi "(http;matchbox.foo:8080)/assets/coreos/1353.7.0/coreos_production_pxe_image.cpio.gz"
}
```
@@ -231,7 +231,7 @@ If you need to serve static assets (e.g. kernel, initrd), `matchbox` can serve a
```
matchbox.foo/assets/
└── coreos
└── 1298.7.0
└── 1353.7.0
├── coreos_production_pxe.vmlinuz
└── coreos_production_pxe_image.cpio.gz
└── 1153.0.0

View File

@@ -30,7 +30,7 @@ The [examples](../examples) statically assign IP addresses to libvirt client VMs
Download the CoreOS image assets referenced in the target [profile](../examples/profiles).
```sh
$ ./scripts/get-coreos stable 1298.7.0 ./examples/assets
$ ./scripts/get-coreos stable 1353.7.0 ./examples/assets
```
Add your SSH public key to each machine group definition [as shown](../examples/README.md#ssh-keys).

View File

@@ -43,13 +43,15 @@ $ cd matchbox-v0.6.0-linux-amd64
### RPM-based distro
On an RPM-based provisioner, install the `matchbox` RPM from the Copr [repository](https://copr.fedorainfracloud.org/coprs/g/CoreOS/matchbox/) using `dnf` or `yum`.
On an RPM-based provisioner (Fedora 24+), install the `matchbox` RPM from the Copr [repository](https://copr.fedorainfracloud.org/coprs/g/CoreOS/matchbox/) using `dnf`.
```sh
dnf copr enable @CoreOS/matchbox
dnf install matchbox
```
RPMs are not currently available for CentOS and RHEL (due to Go version). CentOS and RHEL users should follow the Generic Linux section below.
### CoreOS
On a CoreOS provisioner, rkt run `matchbox` image with the provided systemd unit.
@@ -127,31 +129,39 @@ $ sudo firewall-cmd --zone=MYZONE --add-port=8080/tcp --permanent
$ sudo firewall-cmd --zone=MYZONE --add-port=8081/tcp --permanent
```
## Generate TLS credentials
## Generate TLS Certificates
*Skip this unless you need to enable the gRPC API*
The Matchbox gRPC API allows clients (terraform-provider-matchbox) to create and update Matchbox resources. TLS credentials are needed for client authentication and to establish a secure communication channel. Client machines (those PXE booting) read from the HTTP endpoints and do not require this setup.
The `matchbox` gRPC API allows client apps (terraform-provider-matchbox, Tectonic Installer, etc.) to update how machines are provisioned. TLS credentials are needed for client authentication and to establish a secure communication channel. Client machines (those PXE booting) read from the HTTP endpoints and do not require this setup.
The `cert-gen` helper script generates a self-signed CA, server certificate, and client certificate. **Prefer your organization's PKI, if possible**
If your organization manages public key infrastructure and a certificate authority, create a server certificate and key for the `matchbox` service and a client certificate and key for each client tool.
Otherwise, generate a self-signed `ca.crt`, a server certificate (`server.crt`, `server.key`), and client credentials (`client.crt`, `client.key`) with the `examples/etc/matchbox/cert-gen` script. Export the DNS name or IP (discouraged) of the provisioner host.
Navigate to the `scripts/tls` directory.
```sh
$ cd scripts/tls
```
Export `SAN` to set the Subject Alt Names which should be used in certificates. Provide the fully qualified domain name or IP (discouraged) where Matchbox will be installed.
```sh
# DNS or IP Subject Alt Names where matchbox runs
$ export SAN=DNS.1:matchbox.example.com,IP.1:172.18.0.2
```
Generate a `ca.crt`, `server.crt`, `server.key`, `client.crt`, and `client.key`.
```sh
$ cd examples/etc/matchbox
# DNS or IP Subject Alt Names where matchbox can be reached
$ export SAN=DNS.1:matchbox.example.com,IP.1:192.168.1.42
$ ./cert-gen
```
Place the TLS credentials in the default location:
Move TLS credentials to the matchbox server's default location.
```sh
$ sudo mkdir -p /etc/matchbox
$ sudo cp ca.crt server.crt server.key /etc/matchbox/
$ sudo cp ca.crt server.crt server.key /etc/matchbox
```
Save `client.crt`, `client.key`, and `ca.crt` to use with a client tool later.
Save `client.crt`, `client.key`, and `ca.crt` for later use (e.g. `~/.matchbox`).
## Start matchbox
@@ -203,7 +213,7 @@ Certificate chain
Download a recent CoreOS [release](https://coreos.com/releases/) with signatures.
```sh
$ ./scripts/get-coreos stable 1298.7.0 . # note the "." 3rd argument
$ ./scripts/get-coreos stable 1353.7.0 . # note the "." 3rd argument
```
Move the images to `/var/lib/matchbox/assets`,
@@ -215,7 +225,7 @@ $ sudo cp -r coreos /var/lib/matchbox/assets
```
/var/lib/matchbox/assets/
├── coreos
│   └── 1298.7.0
│   └── 1353.7.0
│   ├── CoreOS_Image_Signing_Key.asc
│   ├── coreos_production_image.bin.bz2
│   ├── coreos_production_image.bin.bz2.sig
@@ -228,7 +238,7 @@ $ sudo cp -r coreos /var/lib/matchbox/assets
and verify the images are acessible.
```sh
$ curl http://matchbox.example.com:8080/assets/coreos/1298.7.0/
$ curl http://matchbox.example.com:8080/assets/coreos/1353.7.0/
<pre>...
```

View File

@@ -29,7 +29,7 @@ $ cd matchbox
Download CoreOS image assets referenced by the `etcd-docker` [example](../examples) to `examples/assets`.
```sh
$ ./scripts/get-coreos stable 1298.7.0 ./examples/assets
$ ./scripts/get-coreos stable 1353.7.0 ./examples/assets
```
For development convenience, add `/etc/hosts` entries for nodes so they may be referenced by name as you would in production.

View File

@@ -30,7 +30,7 @@ $ cd matchbox
Download CoreOS image assets referenced by the `etcd` [example](../examples) to `examples/assets`.
```sh
$ ./scripts/get-coreos stable 1298.7.0 ./examples/assets
$ ./scripts/get-coreos stable 1353.7.0 ./examples/assets
```
## Network

View File

@@ -34,7 +34,7 @@ Install [Terraform][terraform-dl] v0.9+ on your system.
```sh
$ terraform version
Terraform v0.9.2
Terraform v0.9.4
```
Add the `terraform-provider-matchbox` plugin binary on your system.

View File

@@ -64,8 +64,8 @@ Profiles reference an Ignition config, Cloud-Config, and/or generic config by na
"ignition_id": "etcd.yaml",
"generic_id": "some-service.cfg",
"boot": {
"kernel": "/assets/coreos/1298.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1298.7.0/coreos_production_pxe_image.cpio.gz"],
"kernel": "/assets/coreos/1353.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1353.7.0/coreos_production_pxe_image.cpio.gz"],
"args": [
"coreos.config.url=http://matchbox.foo:8080/ignition?uuid=${uuid}&mac=${mac:hexhyp}",
"coreos.first_boot=yes",

View File

@@ -1,87 +0,0 @@
# Kubernetes (with rkt)
The `rktnetes` example provisions a 3 node Kubernetes v1.5.5 cluster with [rkt](https://github.com/coreos/rkt) as the container runtime. The cluster has one controller, two workers, and TLS authentication. An etcd cluster backs Kubernetes and coordinates CoreOS auto-updates (enabled for disk installs).
## Requirements
Ensure that you've gone through the [matchbox with rkt](getting-started-rkt.md) or [matchbox with docker](getting-started-docker.md) guide and understand the basics. In particular, you should be able to:
* Use rkt or Docker to start `matchbox`
* Create a network boot environment with `coreos/dnsmasq`
* Create the example libvirt client VMs
* `/etc/hosts` entries for `node[1-3].example.com` (or pass custom names to `k8s-certgen`)
## Examples
The [examples](../examples) statically assign IP addresses to libvirt client VMs created by `scripts/libvirt`. VMs are setup on the `metal0` CNI bridge for rkt or the `docker0` bridge for Docker. The examples can be used for physical machines if you update the MAC addresses. See [network setup](network-setup.md) and [deployment](deployment.md).
* [rktnetes](../examples/groups/rktnetes) - iPXE boot a Kubernetes cluster
* [rktnetes-install](../examples/groups/rktnetes-install) - Install a Kubernetes cluster to disk
* [Lab examples](https://github.com/dghubble/metal) - Lab hardware examples
## Assets
Download the CoreOS image assets referenced in the target [profile](../examples/profiles).
```sh
$ ./scripts/get-coreos stable 1298.7.0 ./examples/assets
```
Optionally, add your SSH public key to each machine group definition [as shown](../examples/README.md#ssh-keys).
Generate a root CA and Kubernetes TLS assets for components (`admin`, `apiserver`, `worker`) with SANs for `node1.example.com`, etc.
```sh
$ rm -rf examples/assets/tls
$ ./scripts/tls/k8s-certgen
```
**Note**: TLS assets are served to any machines which request them, which requires a trusted network. Alternately, provisioning may be tweaked to require TLS assets be securely copied to each host.
## Containers
Use rkt or docker to start `matchbox` and mount the desired example resources. Create a network boot environment and power-on your machines. Revisit [matchbox with rkt](getting-started-rkt.md) or [matchbox with Docker](getting-started-docker.md) for help.
Client machines should boot and provision themselves. Local client VMs should network boot CoreOS in about a 1 minute and the Kubernetes API should be available after 3-4 minutes (each node downloads a ~160MB Hyperkube). If you chose `rktnetes-install`, notice that machines install CoreOS and then reboot (in libvirt, you must hit "power" again). Time to network boot and provision Kubernetes clusters on physical hardware depends on a number of factors (POST duration, boot device iteration, network speed, etc.).
## Verify
[Install kubectl](https://coreos.com/kubernetes/docs/latest/configure-kubectl.html) on your laptop. Use the generated kubeconfig to access the Kubernetes cluster created on rkt `metal0` or `docker0`.
```sh
$ KUBECONFIG=examples/assets/tls/kubeconfig
$ kubectl get nodes
NAME STATUS AGE
node1.example.com Ready 3m
node2.example.com Ready 3m
node3.example.com Ready 3m
```
Get all pods.
```sh
$ kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system heapster-v1.2.0-4088228293-k3yn8 2/2 Running 0 3m
kube-system kube-apiserver-node1.example.com 1/1 Running 0 4m
kube-system kube-controller-manager-node1.example.com 1/1 Running 0 3m
kube-system kube-dns-v19-l2u8r 3/3 Running 0 4m
kube-system kube-proxy-node1.example.com 1/1 Running 0 3m
kube-system kube-proxy-node2.example.com 1/1 Running 0 3m
kube-system kube-proxy-node3.example.com 1/1 Running 0 3m
kube-system kube-scheduler-node1.example.com 1/1 Running 0 3m
kube-system kubernetes-dashboard-v1.4.1-0iy07 1/1 Running 0 4m
```
## Kubernetes Dashboard
Access the Kubernetes Dashboard with `kubeconfig` credentials by port forwarding to the dashboard pod.
```sh
$ kubectl port-forward kubernetes-dashboard-v1.4.1-SOME-ID 9090 -n=kube-system
Forwarding from 127.0.0.1:9090 -> 9090
```
Then visit [http://127.0.0.1:9090](http://127.0.0.1:9090/).
<img src='img/kubernetes-dashboard.png' class="img-center" alt="Kubernetes Dashboard"/>

View File

@@ -1,6 +1,6 @@
export CGO_ENABLED:=0
VERSION=$(shell ./scripts/git-version)
VERSION=$(shell ./scripts/dev/git-version)
LD_FLAGS="-w -X github.com/coreos/matchbox/matchbox/version.Version=$(VERSION)"
REPO=github.com/coreos/matchbox
@@ -15,11 +15,11 @@ bin/%:
@go build -o bin/$* -v -ldflags $(LD_FLAGS) $(REPO)/cmd/$*
test:
@./scripts/test
@./scripts/dev/test
.PHONY: aci
aci: clean build
@sudo ./scripts/build-aci
@sudo ./scripts/dev/build-aci
.PHONY: docker-image
docker-image:
@@ -40,13 +40,13 @@ vendor:
.PHONY: codegen
codegen: tools
@./scripts/codegen
@./scripts/dev/codegen
.PHONY: tools
tools: bin/protoc bin/protoc-gen-go
bin/protoc:
@./scripts/get-protoc
@./scripts/dev/get-protoc
bin/protoc-gen-go:
@go build -o bin/protoc-gen-go $(REPO)/vendor/github.com/golang/protobuf/protoc-gen-go
@@ -78,7 +78,7 @@ _output/matchbox-%.tar.gz: DEST=_output/$(NAME)
_output/matchbox-%.tar.gz: bin/%/matchbox
mkdir -p $(DEST)
cp bin/$*/matchbox $(DEST)
./scripts/release-files $(DEST)
./scripts/dev/release-files $(DEST)
tar zcvf $(DEST).tar.gz -C _output $(NAME)
.PHONY: all build clean test release

View File

@@ -12,4 +12,4 @@ curl -s -o $DEST/undionly.kpxe http://boot.ipxe.org/undionly.kpxe
cp $DEST/undionly.kpxe $DEST/undionly.kpxe.0
# Any vaguely recent CoreOS grub.efi is fine
curl -s -o $DEST/grub.efi https://stable.release.core-os.net/amd64-usr/1298.7.0/coreos_production_pxe_grub.efi
curl -s -o $DEST/grub.efi https://stable.release.core-os.net/amd64-usr/1353.7.0/coreos_production_pxe_grub.efi

View File

@@ -22,13 +22,13 @@ These examples mount raw Matchbox objects into a Matchbox server's `/var/lib/mat
| Name | Description | CoreOS Version | FS | Docs |
|------------|-------------|----------------|----|-----------|
| simple | CoreOS with autologin, using iPXE | stable/1298.7.0 | RAM | [reference](https://coreos.com/os/docs/latest/booting-with-ipxe.html) |
| simple-install | CoreOS Install, using iPXE | stable/1298.7.0 | RAM | [reference](https://coreos.com/os/docs/latest/booting-with-ipxe.html) |
| grub | CoreOS via GRUB2 Netboot | stable/1298.7.0 | RAM | NA |
| etcd3 | PXE boot 3 node etcd3 cluster with proxies | stable/1298.7.0 | RAM | None |
| etcd3-install | Install a 3 node etcd3 cluster to disk | stable/1298.7.0 | Disk | None |
| bootkube | PXE boot a self-hosted Kubernetes v1.6.4 cluster | stable/1298.7.0 | Disk | [tutorial](../Documentation/bootkube.md) |
| bootkube-install | Install a self-hosted Kubernetes v1.6.4 cluster | stable/1298.7.0 | Disk | [tutorial](../Documentation/bootkube.md) |
| simple | CoreOS with autologin, using iPXE | stable/1353.7.0 | RAM | [reference](https://coreos.com/os/docs/latest/booting-with-ipxe.html) |
| simple-install | CoreOS Install, using iPXE | stable/1353.7.0 | RAM | [reference](https://coreos.com/os/docs/latest/booting-with-ipxe.html) |
| grub | CoreOS via GRUB2 Netboot | stable/1353.7.0 | RAM | NA |
| etcd3 | PXE boot a 3 node etcd3 cluster with proxies | stable/1353.7.0 | RAM | None |
| etcd3-install | Install a 3 node etcd3 cluster to disk | stable/1353.7.0 | Disk | None |
| bootkube | PXE boot a self-hosted Kubernetes v1.6.4 cluster | stable/1353.7.0 | Disk | [tutorial](../Documentation/bootkube.md) |
| bootkube-install | Install a self-hosted Kubernetes v1.6.4 cluster | stable/1353.7.0 | Disk | [tutorial](../Documentation/bootkube.md) |
### Customization

View File

@@ -1,44 +0,0 @@
## gRPC API Credentials
Create FAKE TLS credentials for running the `matchbox` gRPC API examples.
**DO NOT** use these certificates for anything other than running `matchbox` examples. Use your organization's production PKI for production deployments.
Navigate to the example directory which will be mounted as `/etc/matchbox` in examples:
cd matchbox/examples/etc/matchbox
Set certificate subject alt names which should be used by exporting `SAN`. Use the DNS name or IP at which `matchbox` is hosted.
# for examples on metal0 or docker0 bridges
export SAN=IP.1:127.0.0.1,IP.2:172.18.0.2
# production example
export SAN=DNS.1:matchbox.example.com
Create a fake `ca.crt`, `server.crt`, `server.key`, `client.crt`, and `client.key`. Type 'Y' when prompted.
$ ./cert-gen
Creating FAKE CA, server cert/key, and client cert/key...
...
...
...
******************************************************************
WARNING: Generated TLS credentials are ONLY SUITABLE FOR EXAMPLES!
Use your organization's production PKI for production deployments!
## Inpsect
Inspect the generated FAKE certificates if desired.
openssl x509 -noout -text -in ca.crt
openssl x509 -noout -text -in server.crt
openssl x509 -noout -text -in client.crt
## Verify
Verify that the FAKE server and client certificates were signed by the fake CA.
openssl verify -CAfile ca.crt server.crt
openssl verify -CAfile ca.crt client.crt

View File

@@ -4,7 +4,7 @@
"profile": "install-reboot",
"metadata": {
"coreos_channel": "stable",
"coreos_version": "1298.7.0",
"coreos_version": "1353.7.0",
"ignition_endpoint": "http://matchbox.foo:8080/ignition",
"baseurl": "http://matchbox.foo:8080/assets/coreos"
}

View File

@@ -4,7 +4,7 @@
"profile": "install-reboot",
"metadata": {
"coreos_channel": "stable",
"coreos_version": "1298.7.0",
"coreos_version": "1353.7.0",
"ignition_endpoint": "http://matchbox.foo:8080/ignition",
"baseurl": "http://matchbox.foo:8080/assets/coreos"
}

View File

@@ -4,7 +4,7 @@
"profile": "simple-install",
"metadata": {
"coreos_channel": "stable",
"coreos_version": "1298.7.0",
"coreos_version": "1353.7.0",
"ignition_endpoint": "http://matchbox.foo:8080/ignition",
"baseurl": "http://matchbox.foo:8080/assets/coreos"
}

View File

@@ -2,8 +2,8 @@
"id": "bootkube-controller",
"name": "bootkube Ready Controller",
"boot": {
"kernel": "/assets/coreos/1298.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1298.7.0/coreos_production_pxe_image.cpio.gz"],
"kernel": "/assets/coreos/1353.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1353.7.0/coreos_production_pxe_image.cpio.gz"],
"args": [
"root=/dev/sda1",
"coreos.config.url=http://matchbox.foo:8080/ignition?uuid=${uuid}&mac=${mac:hexhyp}",

View File

@@ -2,8 +2,8 @@
"id": "bootkube-worker",
"name": "bootkube Ready Worker",
"boot": {
"kernel": "/assets/coreos/1298.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1298.7.0/coreos_production_pxe_image.cpio.gz"],
"kernel": "/assets/coreos/1353.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1353.7.0/coreos_production_pxe_image.cpio.gz"],
"args": [
"root=/dev/sda1",
"coreos.config.url=http://matchbox.foo:8080/ignition?uuid=${uuid}&mac=${mac:hexhyp}",

View File

@@ -2,8 +2,8 @@
"id": "etcd3-gateway",
"name": "etcd3-gateway",
"boot": {
"kernel": "/assets/coreos/1298.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1298.7.0/coreos_production_pxe_image.cpio.gz"],
"kernel": "/assets/coreos/1353.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1353.7.0/coreos_production_pxe_image.cpio.gz"],
"args": [
"coreos.config.url=http://matchbox.foo:8080/ignition?uuid=${uuid}&mac=${mac:hexhyp}",
"coreos.first_boot=yes",

View File

@@ -2,8 +2,8 @@
"id": "etcd3",
"name": "etcd3",
"boot": {
"kernel": "/assets/coreos/1298.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1298.7.0/coreos_production_pxe_image.cpio.gz"],
"kernel": "/assets/coreos/1353.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1353.7.0/coreos_production_pxe_image.cpio.gz"],
"args": [
"coreos.config.url=http://matchbox.foo:8080/ignition?uuid=${uuid}&mac=${mac:hexhyp}",
"coreos.first_boot=yes",

View File

@@ -2,8 +2,8 @@
"id": "grub",
"name": "CoreOS via GRUB2",
"boot": {
"kernel": "(http;matchbox.foo:8080)/assets/coreos/1298.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["(http;matchbox.foo:8080)/assets/coreos/1298.7.0/coreos_production_pxe_image.cpio.gz"],
"kernel": "(http;matchbox.foo:8080)/assets/coreos/1353.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["(http;matchbox.foo:8080)/assets/coreos/1353.7.0/coreos_production_pxe_image.cpio.gz"],
"args": [
"coreos.config.url=http://matchbox.foo:8080/ignition",
"coreos.first_boot=yes",

View File

@@ -2,8 +2,8 @@
"id": "install-reboot",
"name": "Install CoreOS and Reboot",
"boot": {
"kernel": "/assets/coreos/1298.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1298.7.0/coreos_production_pxe_image.cpio.gz"],
"kernel": "/assets/coreos/1353.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1353.7.0/coreos_production_pxe_image.cpio.gz"],
"args": [
"coreos.config.url=http://matchbox.foo:8080/ignition?uuid=${uuid}&mac=${mac:hexhyp}",
"coreos.first_boot=yes",

View File

@@ -2,8 +2,8 @@
"id": "simple-install",
"name": "Simple CoreOS Alpha Install",
"boot": {
"kernel": "/assets/coreos/1298.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1298.7.0/coreos_production_pxe_image.cpio.gz"],
"kernel": "/assets/coreos/1353.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1353.7.0/coreos_production_pxe_image.cpio.gz"],
"args": [
"coreos.config.url=http://matchbox.foo:8080/ignition?uuid=${uuid}&mac=${mac:hexhyp}",
"coreos.first_boot=yes",

View File

@@ -2,8 +2,8 @@
"id": "simple",
"name": "Simple CoreOS Alpha",
"boot": {
"kernel": "/assets/coreos/1298.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1298.7.0/coreos_production_pxe_image.cpio.gz"],
"kernel": "/assets/coreos/1353.7.0/coreos_production_pxe.vmlinuz",
"initrd": ["/assets/coreos/1353.7.0/coreos_production_pxe_image.cpio.gz"],
"args": [
"coreos.config.url=http://matchbox.foo:8080/ignition?uuid=${uuid}&mac=${mac:hexhyp}",
"coreos.first_boot=yes",

View File

@@ -34,7 +34,7 @@ matchbox_http_endpoint = "http://matchbox.example.com:8080"
matchbox_rpc_endpoint = "matchbox.example.com:8081"
cluster_name = "demo"
container_linux_version = "1298.7.0"
container_linux_version = "1353.7.0"
container_linux_channel = "stable"
ssh_authorized_key = "ADD ME"
```
@@ -57,8 +57,12 @@ k8s_domain_name = "cluster.example.com"
asset_dir = "assets"
```
### Options
You may set `experimental_self_hosted_etcd = "true"` to deploy "self-hosted" etcd atop Kubernetes instead of running etcd on hosts directly. Warning, this is experimental and potentially dangerous.
The example above defines a Kubernetes cluster with 1 controller and 2 workers. Check the `multi-controller.tfvars.example` for an example which defines 3 controllers and one worker.
## Apply
Fetch the [bootkube](../README.md#modules) Terraform [module](https://www.terraform.io/docs/modules/index.html) for bare-metal, which is maintained in the in the matchbox repo.

View File

@@ -0,0 +1,23 @@
matchbox_http_endpoint = "http://matchbox.example.com:8080"
matchbox_rpc_endpoint = "matchbox.example.com:8081"
# ssh_authorized_key = "ADD ME"
cluster_name = "example"
container_linux_version = "1353.7.0"
container_linux_channel = "stable"
# Machines
controller_names = ["node1", "node2", "node3"]
controller_macs = ["52:54:00:a1:9c:ae", "52:54:00:b2:2f:86", "52:54:00:c3:61:77"]
controller_domains = ["node1.example.com", "node2.example.com", "node3.example.com"]
worker_names = ["node4"]
worker_macs = ["52:54:00:d7:99:c7"]
worker_domains = ["node4.example.com"]
# Bootkube
k8s_domain_name = "cluster.example.com"
asset_dir = "assets"
# Optional
# container_linux_oem = ""
# experimental_self_hosted_etcd = "true"

View File

@@ -3,7 +3,7 @@ matchbox_rpc_endpoint = "matchbox.example.com:8081"
# ssh_authorized_key = "ADD ME"
cluster_name = "example"
container_linux_version = "1298.7.0"
container_linux_version = "1353.7.0"
container_linux_channel = "stable"
# Machines

View File

@@ -2,7 +2,7 @@
module "profiles" {
source = "../modules/profiles"
matchbox_http_endpoint = "${var.matchbox_http_endpoint}"
container_linux_version = "1298.7.0"
container_linux_version = "1353.7.0"
container_linux_channel = "stable"
}
@@ -14,7 +14,7 @@ resource "matchbox_group" "default" {
// No selector, matches all nodes
metadata {
container_linux_channel = "stable"
container_linux_version = "1298.7.0"
container_linux_version = "1353.7.0"
container_linux_oem = "${var.container_linux_oem}"
ignition_endpoint = "${var.matchbox_http_endpoint}/ignition"
baseurl = "${var.matchbox_http_endpoint}/assets/coreos"

6
glide.lock generated
View File

@@ -1,5 +1,5 @@
hash: 205de0b66ed059a1f10d3fb36c7d465439818123940a9aaa68ddc71cc3bbfddd
updated: 2017-04-17T17:09:48.864562358-07:00
hash: 7de5ab95677974311285feaa83e24f127bbb4c64a68740bab24d71f491e8b689
updated: 2017-05-24T15:28:05.291154327-07:00
imports:
- name: github.com/ajeddeloh/go-json
version: 73d058cf8437a1989030afe571eeab9f90eebbbd
@@ -80,7 +80,7 @@ imports:
subpackages:
- errorutil
- name: golang.org/x/crypto
version: 5dc8cb4b8a8eb076cbb5a06bc3b8682c15bdbbd3
version: 7e9105388ebff089b3f99f0ef676ea55a6da3a7e
subpackages:
- cast5
- openpgp

View File

@@ -59,7 +59,7 @@ import:
- package: github.com/spf13/cobra
version: 65a708cee0a4424f4e353d031ce440643e312f92
- package: golang.org/x/crypto
version: 5dc8cb4b8a8eb076cbb5a06bc3b8682c15bdbbd3
version: 7e9105388ebff089b3f99f0ef676ea55a6da3a7e
subpackages:
- cast5
- openpgp

View File

@@ -1,11 +0,0 @@
NODE1_NAME=node1
NODE1_MAC=52:54:00:a1:9c:ae
NODE2_NAME=node2
NODE2_MAC=52:54:00:b2:2f:86
NODE3_NAME=node3
NODE3_MAC=52:54:00:c3:61:77
NODE4_NAME=node4
NODE4_MAC=52:54:00:d7:99:c7

View File

@@ -1,7 +1,8 @@
#!/usr/bin/env bash
set -e
GIT_SHA=$(./scripts/git-version)
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
GIT_SHA=$($DIR/git-version)
# Start with an empty ACI
acbuild --debug begin

View File

@@ -4,7 +4,7 @@
set -eu
DEST=${1:-"bin"}
VERSION="v1.5.5"
VERSION="v1.6.4"
URL="https://storage.googleapis.com/kubernetes-release/release/${VERSION}/bin/linux/amd64/kubectl"

View File

@@ -18,9 +18,9 @@ cp README.md $DEST
# scripts
mkdir -p $SCRIPTS/tls
cp scripts/get-coreos $SCRIPTS
cp examples/etc/matchbox/README.md $SCRIPTS/tls
cp examples/etc/matchbox/cert-gen $SCRIPTS/tls
cp examples/etc/matchbox/openssl.conf $SCRIPTS/tls
cp scripts/tls/README.md $SCRIPTS/tls
cp scripts/tls/cert-gen $SCRIPTS/tls
cp scripts/tls/openssl.conf $SCRIPTS/tls
# systemd
mkdir -p $CONTRIB/systemd

View File

@@ -10,7 +10,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
EXAMPLE=${2:-}
BRIDGE=metal0
COREOS_CHANNEL=stable
COREOS_VERSION=1298.7.0
COREOS_VERSION=1353.7.0
MATCHBOX_ARGS=""
ASSETS_DIR="${ASSETS_DIR:-$PWD/examples/assets}"
@@ -91,7 +91,7 @@ function create {
--volume config,kind=host,source=$CONFIG_DIR,readOnly=true \
--mount volume=data,target=/var/lib/matchbox \
$DATA_MOUNT \
quay.io/coreos/matchbox:v0.6.0 -- -address=0.0.0.0:8080 -log-level=debug $MATCHBOX_ARGS
quay.io/coreos/matchbox:23f23c1dcb78b123754ffb4e64f21cd8269093ce -- -address=0.0.0.0:8080 -log-level=debug $MATCHBOX_ARGS
echo "Starting dnsmasq to provide DHCP/TFTP/DNS services"
rkt rm --uuid-file=/var/run/dnsmasq-pod.uuid > /dev/null 2>&1

View File

@@ -9,7 +9,7 @@ set -eou pipefail
GPG=${GPG:-/usr/bin/gpg}
CHANNEL=${1:-"stable"}
VERSION=${2:-"1298.7.0"}
VERSION=${2:-"1353.7.0"}
DEST_DIR=${3:-"$PWD/examples/assets"}
OEM_ID=${OEM_ID:-""}
DEST=$DEST_DIR/coreos/$VERSION

View File

@@ -1,12 +1,9 @@
#!/bin/bash
# Manage VM nodes which have a specific set of hardware attributes.
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
VM_MEMORY=${VM_MEMORY:-1024}
VM_DISK=${VM_DISK:-10}
source "${DIR}/common.sh"
if [ "$EUID" -ne 0 ]
then echo "Please run as root"
exit
@@ -46,6 +43,18 @@ function usage {
COMMON_VIRT_OPTS="--memory=${VM_MEMORY} --vcpus=1 --pxe --disk pool=default,size=${VM_DISK} --os-type=linux --os-variant=generic --noautoconsole --events on_poweroff=preserve"
NODE1_NAME=node1
NODE1_MAC=52:54:00:a1:9c:ae
NODE2_NAME=node2
NODE2_MAC=52:54:00:b2:2f:86
NODE3_NAME=node3
NODE3_MAC=52:54:00:c3:61:77
NODE4_NAME=node4
NODE4_MAC=52:54:00:d7:99:c7
function create_docker {
virt-install --name $NODE1_NAME --network=bridge:docker0,mac=$NODE1_MAC $COMMON_VIRT_OPTS --boot=hd,network
virt-install --name $NODE2_NAME --network=bridge:docker0,mac=$NODE2_MAC $COMMON_VIRT_OPTS --boot=hd,network

5
scripts/tls/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
*
!.gitignore
!README.md
!cert-gen
!openssl.conf

61
scripts/tls/README.md Normal file
View File

@@ -0,0 +1,61 @@
## gRPC TLS Generation
The Matchbox gRPC API allows clients (`terraform-provider-matchbox`) to create and update Matchbox resources. TLS credentials are used for client authentication and to establish a secure communication channel. When the gRPC API is [enabled](../../Documentation/deployment.md#customization), the server requires a TLS server certificate, key, and CA certificate ([locations](../../Documentation/config.md#files-and-directories)).
The `cert-gen` helper script generates a self-signed CA, server certificate, and client certificate. **Prefer your organization's PKI, if possible**
Navigate to the `scripts/tls` directory.
```sh
$ cd scripts/tls
```
Export `SAN` to set the Subject Alt Names which should be used in certificates. Provide the fully qualified domain name or IP (discouraged) where Matchbox will be installed.
```sh
# DNS or IP Subject Alt Names where matchbox runs
$ export SAN=DNS.1:matchbox.example.com,IP.1:172.18.0.2
```
Generate a `ca.crt`, `server.crt`, `server.key`, `client.crt`, and `client.key`.
```sh
$ ./cert-gen
Creating FAKE CA, server cert/key, and client cert/key...
...
...
...
******************************************************************
WARNING: Generated credentials are self-signed. Prefer your
organization's PKI for production deployments.
```
Move TLS credentials to the matchbox server's default location.
```sh
$ sudo mkdir -p /etc/matchbox
$ sudo cp ca.crt server.crt server.key /etc/matchbox
```
Save `client.crt`, `client.key`, and `ca.crt` for later use (e.g. `~/.matchbox`).
*If you are using the local Matchbox [development environment](../../Documentation/getting-started-rkt.md), move server credentials to `examples/etc/matchbox`.*
## Inpsect
Inspect the generated certificates if desired.
```sh
openssl x509 -noout -text -in ca.crt
openssl x509 -noout -text -in server.crt
openssl x509 -noout -text -in client.crt
```
## Verify
Verify that the server and client certificates were signed by the self-signed CA.
```sh
openssl verify -CAfile ca.crt server.crt
openssl verify -CAfile ca.crt client.crt
```

View File

@@ -41,5 +41,5 @@ openssl ca -batch -config openssl.conf -extensions usr_cert -days 365 -notext -m
rm *.csr
echo "*******************************************************************"
echo "WARNING: Generating self-signed TLS-credentials. Its recommended to"
echo "use your own organization's public key infrastructure"
echo "WARNING: Generated credentials are self-signed. Prefer your"
echo "organization's PKI for production deployments."

View File

@@ -1,42 +0,0 @@
#!/bin/bash -e
USAGE="Usage: $(basename $0)
Options:
-d DEST Destination for generated files (default: .examples/assets/tls)
-s SERVER Reachable Server IP for kubeconfig (e.g. node1.example.com)
-m MASTERS Controller Node Names/Addresses in SAN format (e.g. IP.1=10.3.0.1,DNS.1=node1.example.com)
-w WORKERS Worker Node Names/Addresses in SAN format (e.g. DNS.1=node2.example.com,DNS.2=node3.example.com)
-h Show help
"
DEST="./examples/assets/tls"
SERVER="node1.example.com"
MASTERS="IP.1=10.3.0.1,DNS.1=node1.example.com"
WORKERS="DNS.1=node2.example.com,DNS.2=node3.example.com"
while getopts "d:s:m:w:vh" opt; do
case $opt in
d) DEST="$OPTARG" ;;
s) SERVER="$OPTARG" ;;
m) MASTERS="$OPTARG" ;;
w) WORKERS="$OPTARG" ;;
h) echo "$USAGE"; exit;;
*) exit 1;;
esac
done
if [ ! -d "$DEST" ]; then
echo "Creating directory $DEST"
mkdir -p $DEST
fi
# create root CA
./scripts/tls/root-ca $DEST
# create Kubernetes master and worker certificates
./scripts/tls/kubernetes-cert $DEST admin kube-admin
./scripts/tls/kubernetes-cert $DEST apiserver kube-apiserver $MASTERS
./scripts/tls/kubernetes-cert $DEST worker kube-worker $WORKERS
# create a kubeconfig
./scripts/tls/kube-conf $DEST $SERVER

View File

@@ -1,52 +0,0 @@
#!/bin/bash -e
function usage {
echo "USAGE: $0 DEST MASTER_IP"
echo "example: $0 dest/path 192.168.1.21"
}
function base64_encode {
if [[ "$OSTYPE" == darwin* ]]; then
base64 $1
else
base64 -w 0 $1
fi
}
if [ -z "$1" ] || [ -z "$2" ]; then
usage
exit 1
fi
DEST="$1"
MASTER_IP="$2"
ADMIN_CERT_BASE64=$(base64_encode $DEST/admin.pem)
ADMIN_KEY_BASE64="$(base64_encode $DEST/admin-key.pem)"
CA_CERT_BASE64="$(base64_encode $DEST/ca.pem)"
if [ -f "$DEST/kubeconfig" ]; then
echo "$DEST/kubeconfig already exists"
exit 1
fi
cat << EOF > $DEST/kubeconfig
apiVersion: v1
kind: Config
users:
- name: matchbox-user
user:
client-certificate-data: ${ADMIN_CERT_BASE64}
client-key-data: ${ADMIN_KEY_BASE64}
clusters:
- name: matchbox-cluster
cluster:
certificate-authority-data: ${CA_CERT_BASE64}
server: https://${MASTER_IP}:443
contexts:
- context:
cluster: matchbox-cluster
user: matchbox-user
name: matchbox-context
current-context: matchbox-context
EOF
echo "Wrote kubeconfig to $DEST/kubeconfig"

View File

@@ -1,74 +0,0 @@
#!/bin/bash -e
# define location of openssl binary manually since running this
# script under Vagrant fails on some systems without it
OPENSSL=/usr/bin/openssl
function usage {
echo "USAGE: $0 <output-dir> <cert-base-name> <CN> [SAN,SAN,SAN]"
echo " example: $0 ./ssl/ worker kube-worker IP.1=127.0.0.1,IP.2=10.0.0.1"
}
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
usage
exit 1
fi
OUTDIR="$1"
CERTBASE="$2"
CN="$3"
SANS="$4"
if [ ! -d $OUTDIR ]; then
echo "ERROR: output directory does not exist: $OUTDIR"
exit 1
fi
OUTFILE="$OUTDIR/$CN.tar"
if [ -f "$OUTFILE" ];then
exit 0
fi
CNF_TEMPLATE="
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.101 = kubernetes
DNS.102 = kubernetes.default
DNS.103 = kubernetes.default.svc
DNS.104 = kubernetes.default.svc.cluster.local
"
echo "Generating SSL artifacts in $OUTDIR"
CONFIGFILE="$OUTDIR/$CERTBASE-req.cnf"
CAFILE="$OUTDIR/ca.pem"
CAKEYFILE="$OUTDIR/ca-key.pem"
KEYFILE="$OUTDIR/$CERTBASE-key.pem"
CSRFILE="$OUTDIR/$CERTBASE.csr"
PEMFILE="$OUTDIR/$CERTBASE.pem"
CONTENTS="${CAFILE} ${KEYFILE} ${PEMFILE}"
# Add SANs to openssl config
echo "$CNF_TEMPLATE$(echo $SANS | tr ',' '\n')" > "$CONFIGFILE"
$OPENSSL genrsa -out "$KEYFILE" 2048
$OPENSSL req -new -key "$KEYFILE" -out "$CSRFILE" -subj "/CN=$CN" -config "$CONFIGFILE"
$OPENSSL x509 -req -in "$CSRFILE" -CA "$CAFILE" -CAkey "$CAKEYFILE" -CAcreateserial -out "$PEMFILE" -days 365 -extensions v3_req -extfile "$CONFIGFILE"
tar -cf $OUTFILE -C $OUTDIR $(for f in $CONTENTS;do printf "$(basename $f) ";done)
echo "Bundled SSL artifacts into $OUTFILE"
echo "$CONTENTS"

View File

@@ -1,32 +0,0 @@
#!/bin/bash -e
# define location of openssl binary manually since running this
# script under Vagrant fails on some systems without it
OPENSSL=/usr/bin/openssl
function usage {
echo "USAGE: $0 <output-dir>"
echo " example: $0 ./ssl/ca.pem"
}
if [ -z "$1" ]; then
usage
exit 1
fi
OUTDIR="$1"
if [ ! -d $OUTDIR ]; then
echo "ERROR: output directory does not exist: $OUTDIR"
exit 1
fi
OUTFILE="$OUTDIR/ca.pem"
if [ -f "$OUTFILE" ];then
exit 0
fi
# establish cluster CA and self-sign a cert
$OPENSSL genrsa -out "$OUTDIR/ca-key.pem" 2048
$OPENSSL req -x509 -new -nodes -key "$OUTDIR/ca-key.pem" -days 10000 -out "$OUTFILE" -subj "/CN=kube-ca"

View File

@@ -9,8 +9,8 @@ main() {
cleanup
trap cleanup EXIT
./scripts/get-kubectl
./scripts/get-bootkube
./scripts/dev/get-kubectl
./scripts/dev/get-bootkube
./scripts/devnet create bootkube
./scripts/libvirt create

View File

@@ -3,7 +3,7 @@ matchbox_rpc_endpoint = "matchbox.example.com:8081"
ssh_authorized_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDPQFdwVLr+alsWIgYRz9OdqDhnx9jjuFbkdSdpqq4gd9uZApYlivMDD4UgjFazQpezx8DiNhu9ym7i6LgAcdwi+10hE4L9yoJv9uBgbBxOAd65znqLqF91NtV4mlKP5YfJtR7Ehs+pTB+IIC+o5veDbPn+BYgDMJ2x7Osbn1/gFSDken/yoOFbYbRMGMfVEQYjJzC4r/qCKH0bl/xuVNLxf9FkWSTCcQFKGOndwuGITDkshD4r2Kk8gUddXPxoahBv33/2QH0CY5zbKYjhgN6I6WtwO+O1uJwtNeV1AGhYjurdd60qggNwx+W7623uK3nIXvJd3hzDO8u5oa53/tIL fake-test-key"
cluster_name = "example"
container_linux_version = "1298.7.0"
container_linux_version = "1353.7.0"
container_linux_channel = "stable"
# Machines

View File

@@ -10,7 +10,7 @@ main() {
cleanup
trap cleanup EXIT
./scripts/get-kubectl
./scripts/dev/get-kubectl
./scripts/tls/k8s-certgen -d $ASSETS_DIR/tls
./scripts/devnet create k8s
./scripts/libvirt create

View File

@@ -307,8 +307,6 @@ func readToNextPublicKey(packets *packet.Reader) (err error) {
return
}
}
panic("unreachable")
}
// ReadEntity reads an entity (public key, identities, subkeys etc) from the
@@ -504,6 +502,12 @@ func NewEntity(name, comment, email string, config *packet.Config) (*Entity, err
},
}
// If the user passes in a DefaultHash via packet.Config,
// set the PreferredHash for the SelfSignature.
if config != nil && config.DefaultHash != 0 {
e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)}
}
e.Subkeys = make([]Subkey, 1)
e.Subkeys[0] = Subkey{
PublicKey: packet.NewRSAPublicKey(currentTime, &encryptingPriv.PublicKey),

View File

@@ -273,8 +273,6 @@ func consumeAll(r io.Reader) (n int64, err error) {
return
}
}
panic("unreachable")
}
// packetType represents the numeric ids of the different OpenPGP packet types. See

View File

@@ -6,18 +6,21 @@ package packet
import (
"bytes"
"crypto"
"crypto/cipher"
"crypto/dsa"
"crypto/ecdsa"
"crypto/rsa"
"crypto/sha1"
"golang.org/x/crypto/openpgp/elgamal"
"golang.org/x/crypto/openpgp/errors"
"golang.org/x/crypto/openpgp/s2k"
"io"
"io/ioutil"
"math/big"
"strconv"
"time"
"golang.org/x/crypto/openpgp/elgamal"
"golang.org/x/crypto/openpgp/errors"
"golang.org/x/crypto/openpgp/s2k"
)
// PrivateKey represents a possibly encrypted private key. See RFC 4880,
@@ -28,7 +31,7 @@ type PrivateKey struct {
encryptedData []byte
cipher CipherFunction
s2k func(out, in []byte)
PrivateKey interface{} // An *rsa.PrivateKey or *dsa.PrivateKey.
PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or a crypto.Signer.
sha1Checksum bool
iv []byte
}
@@ -54,6 +57,30 @@ func NewElGamalPrivateKey(currentTime time.Time, priv *elgamal.PrivateKey) *Priv
return pk
}
func NewECDSAPrivateKey(currentTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewECDSAPublicKey(currentTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
// NewSignerPrivateKey creates a sign-only PrivateKey from a crypto.Signer that
// implements RSA or ECDSA.
func NewSignerPrivateKey(currentTime time.Time, signer crypto.Signer) *PrivateKey {
pk := new(PrivateKey)
switch pubkey := signer.Public().(type) {
case rsa.PublicKey:
pk.PublicKey = *NewRSAPublicKey(currentTime, &pubkey)
pk.PubKeyAlgo = PubKeyAlgoRSASignOnly
case ecdsa.PublicKey:
pk.PublicKey = *NewECDSAPublicKey(currentTime, &pubkey)
default:
panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey")
}
pk.PrivateKey = signer
return pk
}
func (pk *PrivateKey) parse(r io.Reader) (err error) {
err = (&pk.PublicKey).parse(r)
if err != nil {
@@ -139,6 +166,8 @@ func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
err = serializeDSAPrivateKey(privateKeyBuf, priv)
case *elgamal.PrivateKey:
err = serializeElGamalPrivateKey(privateKeyBuf, priv)
case *ecdsa.PrivateKey:
err = serializeECDSAPrivateKey(privateKeyBuf, priv)
default:
err = errors.InvalidArgumentError("unknown private key type")
}
@@ -198,6 +227,10 @@ func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error {
return writeBig(w, priv.X)
}
func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error {
return writeBig(w, priv.D)
}
// Decrypt decrypts an encrypted private key using a passphrase.
func (pk *PrivateKey) Decrypt(passphrase []byte) error {
if !pk.Encrypted {
@@ -249,6 +282,8 @@ func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
return pk.parseDSAPrivateKey(data)
case PubKeyAlgoElGamal:
return pk.parseElGamalPrivateKey(data)
case PubKeyAlgoECDSA:
return pk.parseECDSAPrivateKey(data)
}
panic("impossible")
}
@@ -324,3 +359,22 @@ func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
return nil
}
func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey)
buf := bytes.NewBuffer(data)
d, _, err := readMPI(buf)
if err != nil {
return
}
pk.PrivateKey = &ecdsa.PrivateKey{
PublicKey: *ecdsaPub,
D: new(big.Int).SetBytes(d),
}
pk.Encrypted = false
pk.encryptedData = nil
return nil
}

View File

@@ -224,6 +224,32 @@ func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *Public
return pk
}
func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey {
pk := &PublicKey{
CreationTime: creationTime,
PubKeyAlgo: PubKeyAlgoECDSA,
PublicKey: pub,
ec: new(ecdsaKey),
}
switch pub.Curve {
case elliptic.P256():
pk.ec.oid = oidCurveP256
case elliptic.P384():
pk.ec.oid = oidCurveP384
case elliptic.P521():
pk.ec.oid = oidCurveP521
default:
panic("unknown elliptic curve")
}
pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
pk.ec.p.bitLength = uint16(8 * len(pk.ec.p.bytes))
pk.setFingerPrintAndKeyId()
return pk
}
func (pk *PublicKey) parse(r io.Reader) (err error) {
// RFC 4880, section 5.5.2
var buf [6]byte
@@ -514,7 +540,6 @@ func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err erro
default:
return errors.SignatureError("Unsupported public key algorithm used in signature")
}
panic("unreachable")
}
// VerifySignatureV3 returns nil iff sig is a valid signature, made by this
@@ -559,7 +584,6 @@ func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err
default:
panic("shouldn't happen")
}
panic("unreachable")
}
// keySignatureHash returns a Hash of the message that needs to be signed for

View File

@@ -216,7 +216,6 @@ func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (er
// V3 public keys only support RSA.
panic("shouldn't happen")
}
panic("unreachable")
}
// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this

View File

@@ -8,10 +8,12 @@ import (
"bytes"
"crypto"
"crypto/dsa"
"crypto/rsa"
"crypto/ecdsa"
"encoding/asn1"
"encoding/binary"
"hash"
"io"
"math/big"
"strconv"
"time"
@@ -515,7 +517,8 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
switch priv.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
sig.RSASignature.bytes, err = rsa.SignPKCS1v15(config.Random(), priv.PrivateKey.(*rsa.PrivateKey), sig.Hash, digest)
// supports both *rsa.PrivateKey and crypto.Signer
sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes))
case PubKeyAlgoDSA:
dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
@@ -532,6 +535,22 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
sig.DSASigS.bytes = s.Bytes()
sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes))
}
case PubKeyAlgoECDSA:
var r, s *big.Int
if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok {
// direct support, avoid asn1 wrapping/unwrapping
r, s, err = ecdsa.Sign(config.Random(), pk, digest)
} else {
var b []byte
b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, nil)
if err == nil {
r, s, err = unwrapECDSASig(b)
}
}
if err == nil {
sig.ECDSASigR = fromBig(r)
sig.ECDSASigS = fromBig(s)
}
default:
err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
}
@@ -539,6 +558,19 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
return
}
// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA
// signature.
func unwrapECDSASig(b []byte) (r, s *big.Int, err error) {
var ecsdaSig struct {
R, S *big.Int
}
_, err = asn1.Unmarshal(b, &ecsdaSig)
if err != nil {
return
}
return ecsdaSig.R, ecsdaSig.S, nil
}
// SignUserId computes a signature from priv, asserting that pub is a valid
// key for the identity id. On success, the signature is stored in sig. Call
// Serialize to write it out.
@@ -546,7 +578,7 @@ func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err e
func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error {
h, err := userIdSignatureHash(id, pub, sig.Hash)
if err != nil {
return nil
return err
}
return sig.Sign(h, priv, config)
}

View File

@@ -50,14 +50,15 @@ type MessageDetails struct {
// If IsSigned is true and SignedBy is non-zero then the signature will
// be verified as UnverifiedBody is read. The signature cannot be
// checked until the whole of UnverifiedBody is read so UnverifiedBody
// must be consumed until EOF before the data can trusted. Even if a
// must be consumed until EOF before the data can be trusted. Even if a
// message isn't signed (or the signer is unknown) the data may contain
// an authentication code that is only checked once UnverifiedBody has
// been consumed. Once EOF has been seen, the following fields are
// valid. (An authentication code failure is reported as a
// SignatureError error when reading from UnverifiedBody.)
SignatureError error // nil if the signature is good.
Signature *packet.Signature // the signature packet itself.
SignatureError error // nil if the signature is good.
Signature *packet.Signature // the signature packet itself, if v4 (default)
SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature
decrypted io.ReadCloser
}
@@ -334,13 +335,15 @@ func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) {
}
var ok bool
if scr.md.Signature, ok = p.(*packet.Signature); !ok {
if scr.md.Signature, ok = p.(*packet.Signature); ok {
scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
} else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok {
scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3)
} else {
scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature")
return
}
scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature)
// The SymmetricallyEncrypted packet, if any, might have an
// unsigned hash of its own. In order to check this we need to
// close that Reader.

View File

@@ -251,7 +251,7 @@ func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
}
// HashIdToString returns the name of the hash function corresponding to the
// given OpenPGP hash id, or panics if id is unknown.
// given OpenPGP hash id.
func HashIdToString(id byte) (name string, ok bool) {
for _, m := range hashToHashIdMapping {
if m.id == id {

View File

@@ -231,7 +231,7 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
}
cipher := packet.CipherFunction(candidateCiphers[0])
// If the cipher specifed by config is a candidate, we'll use that.
// If the cipher specified by config is a candidate, we'll use that.
configuredCipher := config.Cipher()
for _, c := range candidateCiphers {
cipherFunc := packet.CipherFunction(c)