diff --git a/Dockerfile.controller b/Dockerfile.controller index cfe8eab..50da121 100644 --- a/Dockerfile.controller +++ b/Dockerfile.controller @@ -1,9 +1,10 @@ -FROM alpine:edge +FROM alpine:3.20 + ARG $TARGETARCH + WORKDIR /root -RUN echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories \ - && apk add --update --no-cache python3 py3-pillow py3-future py3-jinja2 py3-bottle py3-pip py3-usb imagemagick ttf-opensans libqrencode-tools step-cli openssl bash curl libusb fontconfig ttf-dejavu jq kubectl@testing timg@testing \ +RUN apk add --update --no-cache python3 py3-pillow py3-future py3-jinja2 py3-bottle py3-pip py3-usb imagemagick ttf-opensans libqrencode-tools step-cli openssl bash curl libusb fontconfig ttf-dejavu jq kubectl timg \ && python3 -m venv /venv && . /venv/bin/activate \ && pip3 install --no-cache-dir --upgrade brother_ql \ && curl -sSL https://github.com/pklaus/brother_ql_web/archive/refs/heads/master.tar.gz | tar xz -C /root \ diff --git a/README.md b/README.md index 6cc61e4..0ddbbcb 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,9 @@ work forever, the other URLs and IPs presented in this README are temporary. - [Local development](#local-development) - [Local development on the UI](#local-development-on-the-ui) - [Local development on the controller (that creates PNGs and prints them)](#local-development-on-the-controller-that-creates-pngs-and-prints-them) - - [`pem-to-png`](#pem-to-png) + - [`cert-card`](#cert-card) - [Testing the printer](#testing-the-printer) - - [Testing pem-to-png](#testing-pem-to-png) + - [Testing cert-card](#testing-cert-card) - [Troubleshooting](#troubleshooting) - [From the CLI: `usb.core.USBError: [Errno 13] Access denied (insufficient permissions)`](#from-the-cli-usbcoreusberror-errno-13-access-denied-insufficient-permissions) - [From the CLI: `usb.core.USBError: [Errno 16] Resource busy`](#from-the-cli-usbcoreusberror-errno-16-resource-busy) @@ -227,8 +227,7 @@ https://print-your-cert.cert-manager.io ## Staff: test things -For anyone who is in the cert-manager org and wants to test or debug -things: +For anyone who is authorized and wants to test or debug things: - [Install tailscale](https://tailscale.com/download/). - Run `tailscale up`, it should open something in your browser → "Sign in @@ -243,9 +242,6 @@ things: ssh pi@100.121.173.5 ``` - > The public keys of each cert-manager org member have been added to the - > `authorized_keys` of the Pi. - ## Running everything on the Raspberry Pi (on the booth) Once on the booth, you will need to perform these ten tasks: @@ -273,29 +269,16 @@ upgrade` on the first day of KubeCon in Amsterdam and ended up spending half First, unplug the micro SD card from the Raspberry Pi and plug it into your laptop using a micro-SD-to-SD card adaptor. -Then, install Raspberry OS (Debian Bookworm) on the Pi using the Imager program. -In the Imager program settings, I changed the username to `pi` and the password -to something secret (usually the default password is `raspberry`, I changed it; -see the label on the side of the Raspberry Pi). - -Then, you will need to mount the micro SD card to your laptop using a -SD-to-micro-SD adaptor. Once the SD card is mounted, set the following variable -to where the SD card is mounted: +Then, install Raspberry OS on the microSD card using the Imager program. +In the Imager program settings, change the username to `certmanager` and the password +to something secret. -```sh -# On macOS: -PI=/Volumes/bootfs -``` +Be sure also to enable SSH with password authentication. -Then, enable SSH on the Pi: - -```bash -touch $PI/ssh -``` +You can also use the imager to setup a WiFi connection, which might be helpful +with initial setup at home. -There used to be a way to configure the Wifi password without a screen and -keyboard, but that's not possible anymore with Bookworm -([source](https://www.raspberrypi.com/documentation/computers/configuration.html#connect-to-a-wireless-network)). +At the conference, you should be able to use the GUI to set up a WiFi connection. > If the Wifi doesn't work, somehow SSH into the Pi and run `wpa_cli`: > @@ -322,7 +305,7 @@ keyboard, but that's not possible anymore with Bookworm > sudo ifconfig wlan0 up > ``` -Then, unmount the micro SD card from your laptop and plug it into the Raspberry. +Then, unmount the micro SD card from your laptop and plug it into the Raspberry Pi. ### Booth: Set Up Tailscale on the Raspberry Pi @@ -352,8 +335,13 @@ machine with your Tailnet in . That way, you can stay logged to your tailnet but still be able to access the Raspberry Pi. -Then, go back to your laptop and run the following command to make sure everyone -in the cert-manager org can SSH into the Pi: +#### Allowing SSH Access to cert-manager org members + +If desired, the script below will allow SSH access to cert-manager org members. + +This might be overkill; you can also just download any GitHub user's SSH keys +using `curl -LO https://github.com/.keys` and then append the contents of +that file to `.ssh/authorized_keys`. ```bash curl -sH "Authorization: token $(lpass show github.com -p)" https://api.github.com/orgs/cert-manager/members \ @@ -482,8 +470,7 @@ To create the VM `print-your-cert`, you can use the following command: > [!NOTE] > > Use the GCP zone closest to the KubeCon venue. The examples below use -> `europe-west1-c` (Belgium) since the venue was in Paris (I didn't pick Paris -> as it doesn't have f1-micro VMs). +> `europe-west1-c` (Belgium). Try to pick a zone with low CO2 emissions. > [!NOTE] > @@ -581,6 +568,17 @@ sudo systemctl restart caddy.service EOF ``` +Finally, you'll need to ensure that the tailscale ACLs allow traffic to the pi. + +Visit [the Tailscale admin panel](https://login.tailscale.com/admin/acls/file) and set the "hosts" key +to include the Pi, and ensure that there's an ACL allowing traffic: + +```text +"acls": [ + {"action": "accept", "users": ["*"], "ports": ["raspberrypi:*"]}, +] +``` + ### Prerequisite: install k3s on the Raspberry Pi This prerequisite is useful both for local development and for running the @@ -677,7 +675,7 @@ Now, ssh into the Raspberry Pi and launch the UI: # From your laptop. ssh pi docker rm -f print-your-cert-ui ssh pi docker run -d --restart=always --name print-your-cert-ui --net=host \ - -v '/home/pi/.kube/config:/home/nonroot/.kube/config' \ + -v '/home/certmanager/.kube/config:/home/nonroot/.kube/config' \ ghcr.io/cert-manager/print-your-cert-ui:latest \ --issuer print-your-cert-ca \ --issuer-kind ClusterIssuer \ @@ -761,7 +759,7 @@ Now, SSH into the Raspberry Pi and launch the controller: ```sh ssh pi sudo chmod a+r ~/.kube/config ssh pi docker rm -f print-your-cert-controller -ssh pi docker run -d --restart=always --name print-your-cert-controller --privileged -v /dev/bus/usb:/dev/bus/usb -v /home/pi/.kube/config:/root/.kube/config --net=host ghcr.io/cert-manager/print-your-cert-controller:latest +ssh pi docker run -d --restart=always --name print-your-cert-controller --privileged -v /dev/bus/usb:/dev/bus/usb -v /home/certmanager/.kube/config:/root/.kube/config --net=host ghcr.io/cert-manager/print-your-cert-controller:latest ``` You can also run the "debug" printer UI (brother_ql_web) if you want to make @@ -933,16 +931,16 @@ To use the guestbook, make sure the UI is running locally too (see above). ### Local development on the controller (that creates PNGs and prints them) -The controller is made in two pieces: `pem-to-png` that turns one PEM into two -PNGs, and `print-your-cert-controller` that runs `pem-to-png` every time a +The controller is made in two pieces: `cert-card` which produces a PNG with the label(s), +and `print-your-cert-controller` that runs `cert-card` every time a certificate object in Kubernetes becomes ready. -#### `pem-to-png` +#### `cert-card` -pem-to-png is what turns a PEM file into two PNGs: `front.png` and `back.png`. +`cert-card` which produces a PNG with the label(s) ```sh -brew install imagemagick qrencode step svn +brew install imagemagick qrencode step brew install homebrew/cask-fonts/font-open-sans brew install homebrew/cask-fonts/font-dejavu ``` @@ -950,7 +948,7 @@ brew install homebrew/cask-fonts/font-dejavu To run it, for example: ```sh -./pem-to-png </O=Jetstack" -reqexts v3_req -extensions v3_ca -out ca.crt step certificate create "CN=Foo Bar " foo.crt foo.key --ca ca.crt --ca-key ca.key --password-file /dev/null -pem-to-png " fi @@ -67,32 +69,43 @@ cat >/tmp/crt-$certname line1=$( cat <&2 -echo "$url" | qrencode --type PNG --margin 4 -o - | convert -size 696x492 canvas:white \ - \( -gravity Center -monochrome -filter point -interpolate nearest - -resize 492 \) -composite back-$certname.png + +echo "$url" | qrencode --type PNG --margin 4 -o - | convert -size 696x1109 canvas:white \ + \( -gravity SouthWest -font Open-Sans-Regular -pointsize 22 -fill black -annotate +0-0 "$line1" \) -geometry +0+0 \ + \( -gravity SouthWest -font Open-Sans-Regular -pointsize 22 -fill black -annotate +0+115 "$line2" \) -geometry +0+0 \ + \( -gravity SouthEast -font Open-Sans-Regular -pointsize 44 -fill black -annotate +0-0 "$cardcolor" \) -geometry +0+0 \ + \( -gravity SouthEast -annotate +415+415 -monochrome -filter point -interpolate nearest - -resize 492 \) -geometry +0+0 \ + -background None -layers Flatten front-$certname.png + +#echo "$url" >&2 +#echo "$url" | qrencode --type PNG --margin 4 -o - | convert -size 696x1109 canvas:white \ +# \( -gravity Center -monochrome -filter point -interpolate nearest - -resize 492 \) -composite back-$certname.png diff --git a/cluster_issuer.yaml b/cluster_issuer.yaml index cd47aad..e0559b7 100644 --- a/cluster_issuer.yaml +++ b/cluster_issuer.yaml @@ -23,7 +23,9 @@ spec: organizationalUnits: - cert-manager countries: # Change for the country you're issuing in! - - FR + - US + localities: # Change for the city you're issuing in! + - Salt Lake City duration: 438000h # 50 years. issuerRef: name: root-print-your-cert-ca-issuer diff --git a/guestbook/README.md b/guestbook/README.md index 6bab5f9..936dc85 100644 --- a/guestbook/README.md +++ b/guestbook/README.md @@ -2,12 +2,28 @@ ## Setup -1. Manually copied a locally built guestbook binary, litestream.yml, the systemd service, the cert, key and CA files to the remote VM. -2. Installed litestream manually, then moved litestream.yml to /etc/litestream.yml -3. Moved the systemd unit to /usr/lib/systemd/system -4. Created /var/guestbook -5. Ran the guestbook with init-db to create the db, moved it to /var/guestbook -6. Enabled litestream and the systemd unit +1. Create a VM for running the guestbook in the cert-manager-general GCP project. + - Example CLI command is below + - Be sure to use a debian-based Linux distro +2. On a running k8s cluster with cert-manager (not on the guestbook VM): + - Set up a [Google Cloud DNS secret](https://cert-manager.io/docs/configuration/acme/dns01/google/) + - Be sure to use the cert-manager-general project! + - Apply `letsencrypt-cert.yaml` + - Export the resulting cert and key +3. Manually copy the following files to the remote guestbook VM: + - Locally built guestbook binary + - litestream.yml + - guestbook.service + - The cert chain and key from Let's Encrypt + - The root CA from the Pi (used for mTLS) +4. Install litestream [manually](https://litestream.io/install/debian/) with `dpkg` +5. Move `litestream.yml` to `/etc/litestream.yml` + - Check that the bucket configuration is correct and that the VM's SA has access to the bucket + - Litestream will back the database up to GCS when a write occurs +6. Move `guestbook.service` to `/usr/lib/systemd/system` +7. Create `/var/guestbook` +8. Run `sudo guestbook -init-db -db-path /var/guestbook/guestbook.sqlite` +9. `sudo systemctl enable --now guestbook.service litestream.service` ## Root CA @@ -66,3 +82,24 @@ Certificate: 40:02:20:66:ad:b0:9f:97:d9:56:ec:7c:65:71:7b:07:1d:b6: 64:4a:6c:b7:6d:c6:58:0c:1f:6a:64:d4:98:12:e5:80:50 ``` + +## gcloud CLI for VM + +```bash +gcloud compute instances create print-your-cert-guestbook-20241127-090928 \ + --project=cert-manager-general \ + --zone=us-central1-f \ + --machine-type=e2-medium \ + --network-interface=network-tier=PREMIUM,stack-type=IPV4_ONLY,subnet=default \ + --maintenance-policy=MIGRATE \ + --provisioning-model=STANDARD \ + --service-account=guestbook-sa@cert-manager-general.iam.gserviceaccount.com \ + --scopes=https://www.googleapis.com/auth/devstorage.read_write,https://www.googleapis.com/auth/logging.write,https://www.googleapis.com/auth/monitoring.write,https://www.googleapis.com/auth/service.management.readonly,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/trace.append \ + --tags=https-server \ + --create-disk=auto-delete=yes,boot=yes,device-name=print-your-cert-guestbook,image=projects/debian-cloud/global/images/debian-12-bookworm-v20241009,mode=rw,size=10,type=pd-balanced \ + --no-shielded-secure-boot \ + --shielded-vtpm \ + --shielded-integrity-monitoring \ + --labels=goog-ec-src=vm_add-gcloud \ + --reservation-affinity=any +``` diff --git a/guestbook/guestbook.service b/guestbook/guestbook.service index f68dfb8..0521936 100644 --- a/guestbook/guestbook.service +++ b/guestbook/guestbook.service @@ -6,7 +6,7 @@ After=network.target # TODO: Add custom user # User=guestbook # Group=guestbook -ExecStart=/usr/bin/guestbook -ca-cert /var/guestbook/ca.crt -tls-chain /etc/ssl/tls.chain -tls-key /etc/ssl/tls.key -db-path /var/guestbook/guestbook.sqlite +ExecStart=/usr/bin/guestbook -ca-cert /var/guestbook/ca.crt -tls-chain /etc/ssl/tls.chain -tls-key /etc/ssl/tls.key -db-path /var/guestbook/guestbook.sqlite -listen 0.0.0.0:443 StandardOutput=journal StandardError=journal Type=simple diff --git a/guestbook/letsencrypt-cert.yaml b/guestbook/letsencrypt-cert.yaml new file mode 100644 index 0000000..d07287a --- /dev/null +++ b/guestbook/letsencrypt-cert.yaml @@ -0,0 +1,46 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: le-issuer +spec: + acme: + email: ashley.davis@venafi.com + server: https://acme-v02.api.letsencrypt.org/directory + privateKeySecretRef: + name: le-account-key + solvers: + - dns01: + cloudDNS: + project: cert-manager-general + serviceAccountSecretRef: + name: clouddns-dns01-solver-svc-acct + key: key.json +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: guestbook-tls + namespace: default +spec: + privateKey: + algorithm: ECDSA + size: 256 + secretName: guestbook-tls + commonName: guestbook.print-your-cert.cert-manager.io + subject: + organizations: + - CNCF + organizationalUnits: + - cert-manager + countries: + - GB + - US + - FR + - ES + - NL + dnsNames: + - guestbook.print-your-cert.cert-manager.io + - readonly-guestbook.print-your-cert.cert-manager.io + issuerRef: + name: le-issuer + kind: Issuer diff --git a/landing.html b/landing.html index 947cec5..8896992 100644 --- a/landing.html +++ b/landing.html @@ -16,7 +16,8 @@
- Logo + Logo +

Print Your Certificate

Powered by cert-manager

@@ -43,6 +44,7 @@

Powered by cert-manager

value="{{.Name}}" required placeholder="Your name" + autocomplete="off" />
Powered by cert-manager value="{{.Email}}" required placeholder="Your email address" + autocomplete="off" /> {{if .Error}}
{{.Error}}
@@ -62,7 +65,33 @@

Powered by cert-manager

{{end}}
- +
+

Pick your certificate's color:

+ + + + + + + + + + +
+ + + + + + + + + + + +
+
+

Powered by cert-manager " > Your email will not be displayed on-screen, just your name. These - details are only used to fill in the "Subject" field of the X.509 - certificate, and will be removed within six months. + details are used to fill in the "Subject" field of the X.509 + certificate, and will be removed within six months.
+ We may send a follow-up thank you email using the address provided.

diff --git a/list.html b/list.html index 71b45af..e95b41f 100644 --- a/list.html +++ b/list.html @@ -65,8 +65,5 @@

Print Your Certificate

Design by Constantin Chirila

- {{if .Debug}} -
{{.Debug}}
- {{end}} diff --git a/main.go b/main.go index 8123730..6446852 100644 --- a/main.go +++ b/main.go @@ -61,7 +61,8 @@ const ( AnnotationPrint = "print" ConditionPrinted = "Printed" - AnnotationFetchKey = "fetch-key" + AnnotationFetchKey = "fetch-key" + AnnotationCardColor = "card-color" ) // Config attempts to load the in-cluster config and falls back to using @@ -157,9 +158,14 @@ func landingPage(kclient kubernetes.Interface, cmclient cmversioned.Interface) f personName := r.URL.Query().Get("name") email := r.URL.Query().Get("email") + cardColor := strings.ToUpper(r.URL.Query().Get("cardcolor")) - // Happily return early if the name or email haven't been - // provided yet. + if cardColor == "" { + // default to pink since that's usually the color we have most of + cardColor = "P" + } + + // Happily return early if the name or email haven't been provided yet. if personName == "" && email == "" { w.WriteHeader(400) tmpl.ExecuteTemplate(w, "landing.html", landingPageData{Name: personName, Email: email, CountPrinted: printed, CountPending: pending, Message: "Welcome! To get your certificate, fill in your name and email."}) @@ -202,7 +208,8 @@ func landingPage(kclient kubernetes.Interface, cmclient cmversioned.Interface) f ObjectMeta: metav1.ObjectMeta{ Name: certName, Annotations: map[string]string{ - AnnotationFetchKey: fetchKey, + AnnotationFetchKey: fetchKey, + AnnotationCardColor: cardColor, }, }, Spec: certmanagerv1.CertificateSpec{ @@ -211,7 +218,11 @@ func landingPage(kclient kubernetes.Interface, cmclient cmversioned.Interface) f Subject: &certmanagerv1.X509Subject{ // Update this with the country you're issuing in! Countries: []string{ - "FR", + "US", + }, + // Update this with the city you're issuing in! + Localities: []string{ + "Salt Lake City", }, }, SecretName: certName, @@ -1104,7 +1115,7 @@ curl --cert chain.pem --key pkey.pem https://guestbook.print-your-cert.cert-mana -d "message=I'm a star" ` -const signREADME = `Thanks for downloading your certificate from the cert-manager booth at KubeCon Paris 2024! +const signREADME = `Thanks for downloading your certificate from the cert-manager booth at KubeCon Salt Lake City 2024! You can run sign.sh to sign the guestbook - feel free to customise the message! diff --git a/pem-to-png b/pem-to-png index 4f92c3a..a7007bc 100755 --- a/pem-to-png +++ b/pem-to-png @@ -1,5 +1,8 @@ #! /usr/bin/env bash +# IMPORTANT: pem-to-png is the old version, kept for reference +# cert-card is the new version + # entr bash -c "./pem-to-png &1); then + if ! out=$(cert-card "$certname" "$annotation_value_fetchkey" "$annotation_value_cardcolor" <<<"$pem" 2>&1); then printf "%s: failed to generate front-....png and back-....png.\n" "$(jq -r .metadata.name <<<"$cert")" "$(tr $'\n' ' ' <<<"$out")" continue fi @@ -71,7 +74,8 @@ kubectl get cert -ojson --watch | jq -c --unbuffered | while read -r cert; do out="mocked output for front print" brother_rc=0 else - out=$(brother_ql --model QL-820NWB --printer usb://0x04f9:0x209d print --label 62 "front-$certname.png" 2>&1) + # out=$(brother_ql --model QL-820NWB --printer usb://0x04f9:0x209d print --label 62 "front-$certname.png" 2>&1) + out=$(brother_ql --model QL-820NWB --printer usb://0x04f9:0x209d print --label 62x100 "front-$certname.png" 2>&1) brother_rc=$? fi @@ -94,29 +98,32 @@ kubectl get cert -ojson --watch | jq -c --unbuffered | while read -r cert; do out= brother_rc= - if [[ -n $mock ]]; then - out="mocked output for front print" - brother_rc=0 - else - out=out=$(brother_ql --model QL-820NWB --printer usb://0x04f9:0x209d print --label 62 back-$certname.png 2>&1) - brother_rc=$? - fi - - if [[ $brother_rc != 0 ]]; then - printf "%s: failed to print back-$certname.png: %s\n" "$(jq -r .metadata.name <<<"$cert")" "$(tail -1 <<<"$out")" - if ! out=$(kubectl patch cert "$(jq -r .metadata.name <<<"$cert")" --subresource status --type=json -p ' - [{ - "op": "add", "path": "/status/conditions", "value":[{ - "type": "Printed", - "status": "False", - "reason": "Error", - "message": "brother_ql: '"$(tail -1 <<<"$out")"'" - }] - }]' 2>&1); then - printf "%s: failed to set the 'Printed' condition to 'False': %s\n" "$(jq -r .metadata.name <<<"$cert")" "$(tr $'\n' ' ' <<<"$out")" - fi - continue - fi + # This is commented as in SLC we printed labels on one big sticker rather than two smaller stickers + # But we might need to uncomment to return to using smaller stickers + #if [[ -n $mock ]]; then + # out="mocked output for back print" + # brother_rc=0 + #else + # # out=out=$(brother_ql --model QL-820NWB --printer usb://0x04f9:0x209d print --label 62 back-$certname.png 2>&1) + # out=out=$(brother_ql --model QL-820NWB --printer usb://0x04f9:0x209d print --label 62x100 back-$certname.png 2>&1) + # brother_rc=$? + #fi + + #if [[ $brother_rc != 0 ]]; then + # printf "%s: failed to print back-$certname.png: %s\n" "$(jq -r .metadata.name <<<"$cert")" "$(tail -1 <<<"$out")" + # if ! out=$(kubectl patch cert "$(jq -r .metadata.name <<<"$cert")" --subresource status --type=json -p ' + # [{ + # "op": "add", "path": "/status/conditions", "value":[{ + # "type": "Printed", + # "status": "False", + # "reason": "Error", + # "message": "brother_ql: '"$(tail -1 <<<"$out")"'" + # }] + # }]' 2>&1); then + # printf "%s: failed to set the 'Printed' condition to 'False': %s\n" "$(jq -r .metadata.name <<<"$cert")" "$(tr $'\n' ' ' <<<"$out")" + # fi + # continue + #fi # Now that the certificate is printed, we can update the status of # the certificate. diff --git a/rebuild-controller.sh b/rebuild-controller.sh new file mode 100755 index 0000000..26e60cb --- /dev/null +++ b/rebuild-controller.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -eu -o pipefail + +docker buildx create --name mybuilder || : + +docker buildx build -f Dockerfile.controller --platform linux/arm64 \ + -t ghcr.io/cert-manager/print-your-cert-controller:latest \ + -o type=docker,dest=print-your-cert-controller.tar . + +# Example scp command over tailscale +# scp print-your-cert-controller.tar certmanager@100.84.86.89: diff --git a/rebuild-ui.sh b/rebuild-ui.sh new file mode 100755 index 0000000..92bfeed --- /dev/null +++ b/rebuild-ui.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -eu -o pipefail + +KO_DOCKER_REPO=ghcr.io/cert-manager/print-your-cert-ui ko build . --platform linux/arm64 --tarball print-your-cert-ui.tar --push=false --bare + +# Example scp command over tailscale +# scp print-your-cert-ui.tar certmanager@100.84.86.89: diff --git a/static/images/logo_grad.svg b/static/images/logo_grad.svg new file mode 100644 index 0000000..c24b1c3 --- /dev/null +++ b/static/images/logo_grad.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/static/styles.css b/static/styles.css index b389110..568ccb6 100644 --- a/static/styles.css +++ b/static/styles.css @@ -9,7 +9,7 @@ html { background-attachment: fixed; font-family: "Montserrat", Helvetica, Arial, serif; color: #fff; - font-size: 16px; + font-size: 24px; } .wrapper { @@ -227,11 +227,12 @@ tr th { border-bottom: 2px solid rgba(1, 75, 188, 0.5); font-size: 20px; } +/* tr th:last-child, tr td:last-child { text-align: right; width: 200px; -} +}*/ tr td { padding: 12px 10px; border-bottom: 2px solid rgba(1, 75, 188, 0.15); @@ -244,3 +245,6 @@ tr td.limit { max-width: 200px; } +input[type="radio"] { + box-shadow: 0px; +}