🔏 Signering

Signering er for å lage et kryptografisk stempel på autensitet og integritet.

Autensitet: Ved å signere kan andre verifisere på opphavet

Integritet: Ved å signere kan man sikre at det som blir levert, er det som er tiltenkt levert, uten endringer.

Krav: Ved å sette krav til signering kan man også stenge for at uønskede aktører kan kjøre opp tjenester som ikke er signert.

Cosign fra Sigstore brukes for signering av images på en enkel måte. I tillegg kan Cosign signere andre typer som filer, artifakter, BOM osv…

Installasjon

Oppdatert guide er alltid tilgjengelig på Cosign Installation

Etter installasjonen logger du inn i registeret her

GO

go install github.com/sigstore/cosign/v2/cmd/cosign@latest

Homebrew

brew install cosign

Binary

ARCH=$(dpkg --print-architecture)
wget "https://github.com/sigstore/cosign/releases/download/v2.0.2/cosign-linux-$ARCH"
sudo mv cosign-linux-$ARCH /usr/local/bin/cosign
sudo chmod +x /usr/local/bin/cosign

Signeringsmetodikker

Nøkkelpar

Her brukes nøkkelpar (private/public key) for å signere og verifisere images.

Signering med nøkkelpar er den enkleste formen for signering, og kan enkelt integreres i ethvert team.

cosign generate-key-pair
cosign sign --key cosign.key alpine/curl

Privat nøkkel må sikres på et forsvarlig sted.

Key Management System (KMS)

Her benytter man en ekstern aktør for å holde på og sikre privatnøkkelen. Et bra KMS vil aldri kunne gi fra seg en privatnøkkel, det eneste man får tilgang på er den offentlige nøkkelen.

All signering skjer i selve KMS. Ved signering av images er det digest verdien som blir sendt til KMS for signering.

I dette eksemplet skal vi bruke HashiCorp Vault som KMS tilbyder. Dette forutsetter at transit engine er skrudd på ihht dokumentasjonen.

cosign generate-key-pair --kms hashivault://signature

cosign sign --kms hashivault://signature git.local/gitea/nyancat

Sertifikater

Sertifikat signering og sertifisering er best brukt i større organisasjoner, der en organisasjon kan utstede ut fra et eget sertifikat, et nytt sertifikat for hvert enkelt team. Ut fra dette sertifikatet som inneholder tre komponenter, en privatnøkkel, en offentlig nøkkel for sertifikatet og den offentlige nøkkelen til utsteder, kan man generere en cosign nøkkel for signering. En organisasjon vil så sette krav til at alle signeringer referer til denne tillitskjeden av sertifikater, og at alle har opphav fra organisasjons sertifikatet.

Se Hvordan lage en sertifikat kjede lokalt med OpenSSL for veiledning på hvordan man lager en gyldig sertifikat kjede lokalt.

OIDC

Open ID Connect


Veiledere

Bruke clusterets sertifikater

kubectl get secrets -n kyverno kyverno-tls-secret -o json | jq -r '.data["tls.crt"]' | base64 -d > cert.crt
kubectl get secrets -n kyverno kyverno-tls-secret -o json | jq -r '.data["tls.key"]' | base64 -d > cert.key
kubectl get secrets -n kyverno kyverno-tls-secret -o json | jq -r '.data["ca.crt"]' | base64 -d > ca.crt
cosign import-key-pair --key cert.key
cosign sign --key import-cosign.key --yes --cert cert.crt --cert-chain ca.crt git.local/gitea/nyancat

HashiCorp Vault PKI

HashiCorp Vault kan brukes som en PKI tilbyder for utstedelse av sertifikater og sertifikat kjede. Dette er veiledning for å sette opp Vault som en autorisert sertifikat tilbyder.

OpenSSL sertifikater

For å ta i bruk sertifikater må man lage en sertifikat kjede som er gyldig. Dette kan du gjøre med følgende fremgangsmetode:

  1. Generate a private key for Root certificate
# Husk å bruk passord her, ellers funker det ikke!
openssl genrsa -des3 -out rootCA.key 2048
  1. Generate Root certificate
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1825 -out rootCA.crt

in Certificate generation set following values

C = IN, ST = DEL, L = DEL, O = example.com, OU = sigstore, CN = sigstore, emailAddress = foo@example.com
  1. Generate Private key for Intermediate certificate
openssl genrsa -out intermediateCA.key 2048
  1. Generate CSR for Intermediate certificate
openssl req -new -key intermediateCA.key -out intermediateCA.csr

in Certificate generation set following values

C = IN, ST = DEL, L = DEL, O = example.com, OU = sigstore-sub, CN = sigstore-sub, emailAddress = foo@example.com
  1. Create intermediate certificate config file by name “intermediateConfigFile” having content
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
  1. Create intermediate certificate
openssl x509 -req -in intermediateCA.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -CAserial intermediateca.srl -out intermediateCA.crt -days 1825 -sha256 -extfile intermediateConfigFile
  1. Create Private key for leaf certificate
openssl genrsa -out leafCA.key 2048
  1. Create CSR for Leaf certificate
openssl req -new -key leafCA.key -out leafCA.csr

in certificate generation set following values

C = IN, ST = DEL, L = DEL, O = example.com, OU = sigstore-leaf, CN = sigstore-leaf, emailAddress = foo@example.com
  1. Create Leaf certificate config file by name “leafConfigFile” having content
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage=codeSigning
subjectAltName=email:copy
  1. Create Leaf certificate
openssl x509 -req -in leafCA.csr -CA intermediateCA.crt -CAkey intermediateCA.key -CAcreateserial -CAserial leafca.srl -out leafCA.crt -days 1825 -sha256 -extfile leafConfigFile
  1. Generate Certificate chain by concatinating Intermediate certificate and Root certificate
cat intermediateCA.crt rootCA.crt > certChain.crt
  1. Import key
cosign import-key-pair --key leafCA.key
  1. Sign cosign
# Fungerer bare med verifisering
cosign sign --key import-cosign.key git.local/gitea/nyancat

cosign sign --key import-cosign.key --yes --cert leafCA.crt --cert-chain intermediateCA.crt git.local/gitea/nyancat
  1. Verify signature
cosign verify git.local/gitea/nyancat --cert leafCA.crt --cert-chain certChain.crt | jq .

cosign verify git.local/gitea/nyancat --cert leafCA.crt --cert-chain intermediateCA.crt | jq
  1. Check status
kubectl get AdmissionReport -A

Kyverno

Key-pair

Lagre følgende clusterPolicy til kyverno namespace.

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: check-image
spec:
  validationFailureAction: Enforce
  rules:
    - name: verify-signature
      match:
        any:
        - resources:
            kinds:
              - Pod
      - resources:
          namespaces:
            - nyan
      verifyImages:
      - imageReferences:
        - "*"
        repository: "git.local/gitea/signatures"
        attestors:
        - count: 1
          entries:
          - keys:
              publicKeys: |-
                -----BEGIN PUBLIC KEY-----
                MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE4HP6Ra2KaCIv4P9uo6eyyNAWwGhv
                3hj80XA+qMlyasOTo/K1deFyzEDOfPQh751I05Wr3Mn4rWyk3aTCYHFpDQ==
                -----END PUBLIC KEY-----

KMS

KMS som HashiCorp Vault kan verifiseres ved følgende

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: check-image
  namespace: kyverno
spec:
  background: true
  rules:
  - match:
      any:
      - resources:
          kinds:
          - Pod
          namespaces:
          - nyan
    name: verify-signature
    verifyImages:
    - attestors:
      - entries:
        - keys:
            publicKeys: "hashivault://transit"
      imageReferences:
       - '*'
      mutateDigest: true
      repository: git.local/gitea/signatures
      required: true
      verifyDigest: true
  validationFailureAction: Enforce

Dette krever følgende miljøvariabler i kyverno deploymentet, som enten kan patches eller legges til values filen:

envVars:
  - name: "VAULT_ADDR"
    value: "https://vault.local"
  - name: "VAULT_TOKEN"
    valueFrom:
      secretKeyRef:
        name: vault-secret
        key: token

Og da følgende hemmelighet:

kubectl create secret generic -n kyverno vault-secret --from-literal=token=$(cat vault-secrets.json | jq -r .root_token)

Sertifikater

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: check-image
spec:
  background: true
  rules:
  - match:
      any:
      - resources:
          kinds:
          - Pod
          namespaces:
          - nyan
    name: verify-signature
    verifyImages:
    - attestors:
      - entries:
        - certificates:
            certChain: |-
              -----BEGIN CERTIFICATE-----
              MIIDojCCAoqgAwIBAgIUTQLqzBaqMfEUsBUJnFSCgKy6OO0wDQYJKoZIhvcNAQEL
              BQAwFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wHhcNMjMwNDI2MDU1ODUwWhcNMjgw
              NDI0MDU1OTIwWjAtMSswKQYDVQQDEyJleGFtcGxlLmNvbSBJbnRlcm1lZGlhdGUg
              QXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvKxVCdzN
              JRTION/Yw0CtQAGmeo66BNp+L3zJ+qYy/A/lyxYaZSZUzkkv1/miwdxGD+2RgGNr
              K9FJOx6+DwR7rmVU2NJiEgY/nqpk63vab9JBHk4+BhYDlMCVYJKCn6pLZ1GnGZnv
              w05zhO1zk/YuT8YUMj4HT20Mc0V/NSzTppq0DBrAymoFoA2PvmLPhvqM+HqD5xkC
              6TYh5oWCVGMSWSSJcE97bPUkIa2+13ZJIn3vfUOsiZnS2er61PoDUtdx41mccQ3s
              oxKPPF937QELYaqCYhI4OAwvckd4U+Iy6VQ1zKvaIflYCO0d1KRWOms+6eKcx8RG
              Ml4szfua2Nh+7QIDAQABo4HQMIHNMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
              BTADAQH/MB0GA1UdDgQWBBTCMBYPHRokTKIkPJ5bQOZ1zRi3EzAfBgNVHSMEGDAW
              gBRgcto9dUQ9wOtk2OBa/Ijut5nYCDA5BggrBgEFBQcBAQQtMCswKQYIKwYBBQUH
              MAKGHWh0dHBzOi8vdmF1bHQubG9jYWwvdjEvcGtpL2NhMC8GA1UdHwQoMCYwJKAi
              oCCGHmh0dHBzOi8vdmF1bHQubG9jYWwvdjEvcGtpL2NybDANBgkqhkiG9w0BAQsF
              AAOCAQEAXKGn5NdCTqfTgW0r45LInU9bOEbSNpUonePSpuy4GVJx+Sf9CIQT6hvB
              IWlcsK8Fi44zXqtsuZxnsi4LHsZJZ/+aE1xwDjNcx7Jpk94qKEaXt4XGztbG/bZJ
              TvQ5iLP8TSx0CvKkVH+jOtKUFwey2utOdWjdNn5YJ5i8mrmhL+gDfYnzYB2BMNVq
              VOiFuZTKswDxzQsWQG9jPeYeUcjitX3FaVTWQPCN7UmsnToy2RuNFSLF/RzUmrY9
              pt7RpmKe3XK+OLB6R1e0RqTnOcmYGc9mZiHvOP/Mv8fhyDX1HpO5WaRHdqKhgBq9
              XPbne+1g+ICyjYzYG9LpTFz4hQ7Q+Q==
              -----END CERTIFICATE-----
      imageReferences:
      - '*'
      mutateDigest: true
      repository: git.local/gitea/signatures
      required: true
      verifyDigest: true
  validationFailureAction: Enforce

Signer ved å bruke følgende:

cosign sign --key import-cosign.key --yes --cert cert.crt --cert-chain cert-chain.crt curlimages/curl

Lagre innholdet i egen yaml fil og kjør det opp i kyverno namespace.

kubectl apply -f check-image-policy.yml -n kyverno

Verifiser

Verifiser at det fungerer ved å prøve å kjøre opp en pod som ikke er signert:

kubectl run curl-pod --rm -it --image=curlimages/curl -n nyan -- sh

Signer så curlimages/curl og prøv å kjøre samme kommando på nytt.

Annet

Login register

For å kunne pushe til registeret må man først logge inn, det kan gjøres med denne kommandoen

cosign login git.local -u gitea -p gitops

Environment variabler

SIGSTORE_ROOT_FILE=./CA.crts
COSIGN_REPOSITORY=git.local/gitea/signatures
  • COSIGN_REPOSITORY: hvis man ønsker et eget repo for signaturene, f.eks hvis man ikke har skrivetilgang til container registerets om er et tilfelle om man ønsker å signere et image fra en tredje part.