# Verify Image Signatures

## Overview  
Kloudfuse signs all container images stored in AWS Elastic Container Registry (ECR) using asymmetric cryptography. This ensures that:
- Images originate from Kloudfuse
- Images have not been tampered with or modified
- You can verify image authenticity without needing Kloudfuse’s private key

### Signing Key  
AWS KMS key owned by Kloudfuse

### Key ARN  
`arn:aws:kms:us-west-2:502496443919:alias/kfuse-cosign-signing-key`

### ECR Registry  
`502496443919.dkr.ecr.us-west-2.amazonaws.com/kfuse`

### Signature Algorithm  
ECDSA with P-256 curve (NIST standard)

## How Image Signatures Work
### Signing Process (Kloudfuse)
1. Kloudfuse signs images using a **private key** stored securely in AWS KMS  
2. Signatures are stored as OCI artifacts in ECR with `.sig` tags  
3. The private key never leaves AWS KMS

### Verification Process (Customers)
1. You verify signatures using the corresponding **public key**  
2. The public key is derived from the KMS key using read-only access  
3. No secrets or credentials are required for verification

|     |     |
| --- | --- |
|  | **Asymmetric Cryptography**<br>- **Private Key** → Only Kloudfuse can sign images<br>  <br>- **Public Key** → Anyone can verify signatures (proving authenticity) |

## Method 1: Verify Using AWS KMS (Recommended)
This method uses AWS KMS directly for verification and is recommended for production environments.
### Prerequisites
1. **AWS IAM Permissions**

```json
{
     "Version": "2012-10-17",
     "Statement": [
       {
         "Effect": "Allow",
         "Action": [
           "kms:GetPublicKey",
           "kms:Verify",
           "kms:DescribeKey"
         ],
         "Resource": "arn:aws:kms:us-west-2:502496443919:key/*"
       }
     ]
}
```

2. **Cosign installed** 
3. **ECR access**

### Verify an Image
Run the following command to verify a Kloudfuse image:

```bash
cosign verify \
  --key awskms:///arn:aws:kms:us-west-2:502496443919:alias/kfuse-cosign-signing-key \
  502496443919.dkr.ecr.us-west-2.amazonaws.com/kfuse/ui:0.1.0-b2274ac0
```

**Successful verification output:**

```text
Verification for 502496443919.dkr.ecr.us-west-2.amazonaws.com/kfuse/ui:0.1.0-b2274ac0 --
The following checks were performed on each of these signatures:
  - The cosign claims were validated
  - Existence of the claims in the transparency log was verified offline
  - The signatures were verified against the specified public key
```

### Example: Verify in CI/CD Pipeline
This example shows how to verify Kloudfuse images in a GitLab CI pipeline:

```yaml
verify-kfuse-image:
  stage: verify
  image: alpine:latest
  variables:
    IMAGE_NAME: ui
    IMAGE_TAG: "0.1.0-b2274ac0"
    COSIGN_VERSION: "v2.4.0"
    KMS_KEY: "awskms:///arn:aws:kms:us-west-2:502496443919:alias/kfuse-cosign-signing-key"
  before_script:
    - apk add --no-cache curl aws-cli
    - curl -sSfL "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign-linux-amd64" -o /usr/local/bin/cosign
    - chmod +x /usr/local/bin/cosign
  script:
    - |
      IMAGE_REF="502496443919.dkr.ecr.us-west-2.amazonaws.com/kfuse/${IMAGE_NAME}:${IMAGE_TAG}"
      if cosign verify --key "${KMS_KEY}" "${IMAGE_REF}"; then
        echo "✅ Image signature verified successfully"
      else
        echo "❌ Image signature verification FAILED"
        exit 1
      fi
```

## Method 2: Verify Using Public Key File
This method uses a downloaded public key file and does not require AWS credentials for verification.
### Get the Public Key
Kloudfuse provides the public key directly. You can also extract it yourself using the following command:

```bash
aws kms get-public-key \
  --key-id arn:aws:kms:us-west-2:502496443919:alias/kfuse-cosign-signing-key \
  --region us-west-2 \
  --query 'PublicKey' \
  --output text | base64 --decode > kfuse-cosign-public-key.pem
```

**Public Key (PEM format):**

```text
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEg5MTbws6zhPPlz8EKgcyOX+y2BCd
bLVOMHCG3FjpS4JGijEcbKJ9gd13lHbWZuZkFk2I3BVZIctOjvrf+BgIgg==
-----END PUBLIC KEY-----
```

### Verify Using Public Key

```bash
cosign verify \
  --key kfuse-cosign-public-key.pem \
  502496443919.dkr.ecr.us-west-2.amazonaws.com/kfuse/ui:0.1.0-b2274ac0
```

### Advantages
- No AWS credentials needed
- Faster (no KMS API calls)
- Works in air-gapped environments

### Disadvantages
- Need to manage and distribute a public key file
- Requires manual updates if the key is rotated

## Install Cosign
### Package Managers (Recommended)
**Homebrew (macOS/Linux):**

```bash
brew install cosign
cosign version
```

**Alpine Linux:**

```bash
apk add cosign
```

**Arch Linux:**

```bash
pacman -S cosign
```

### Binary Installation
#### Linux (x86_64)

```bash
set -e  # Exit on error

# Pin to specific version; update periodically from https://github.com/sigstore/cosign/releases
COSIGN_VERSION="v3.0.3"

# Download cosign binary and checksums
curl -sSfL "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign-linux-amd64" -o /tmp/cosign-linux-amd64
curl -sSfL "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign_checksums.txt" -o /tmp/checksums.txt

# Verify checksum (filename must match checksums.txt)
cd /tmp && sha256sum --check --ignore-missing checksums.txt

# Install cosign
chmod +x /tmp/cosign-linux-amd64
sudo mv /tmp/cosign-linux-amd64 /usr/local/bin/cosign

# Verify installation
cosign version
```

#### macOS (ARM64)

```bash
set -e  # Exit on error

COSIGN_VERSION="v3.0.3"

# Download cosign binary and checksums
curl -sSfL "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign-darwin-arm64" -o /tmp/cosign-darwin-arm64
curl -sSfL "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign_checksums.txt" -o /tmp/checksums.txt

# Verify checksum
cd /tmp && sha256sum --check --ignore-missing checksums.txt

# Install cosign
chmod +x /tmp/cosign-darwin-arm64
sudo mv /tmp/cosign-darwin-arm64 /usr/local/bin/cosign

# Verify installation
cosign version
```

#### macOS (Intel x86_64)

```bash
set -e  # Exit on error

COSIGN_VERSION="v3.0.3"

# Download cosign binary and checksums
curl -sSfL "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign-darwin-amd64" -o /tmp/cosign-darwin-amd64
curl -sSfL "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign_checksums.txt" -o /tmp/checksums.txt

# Verify checksum
cd /tmp && shasum -a 256 --check --ignore-missing checksums.txt

# Install cosign
chmod +x /tmp/cosign-darwin-amd64
sudo mv /tmp/cosign-darwin-amd64 /usr/local/bin/cosign

# Verify installation
cosign version
```

### Container Image

```bash
docker run --rm \
  -v $(pwd):/workspace \
  ghcr.io/sigstore/cosign/cosign:v3.0.3 \
  verify --key awskms:///arn:aws:kms:us-west-2:502496443919:alias/kfuse-cosign-signing-key \
  502496443919.dkr.ecr.us-west-2.amazonaws.com/kfuse/ui:0.1.0-b2274ac0
```

## Automated Verification in Kubernetes
Use admission controllers to automatically verify signatures before pod creation.
### Kyverno Policy Example

```yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-kfuse-images
spec:
  validationFailureAction: Enforce
  background: false
  rules:
    - name: verify-signature
      match:
        any:
        - resources:
            kinds:
              - Pod
      verifyImages:
      - imageReferences:
        - "502496443919.dkr.ecr.us-west-2.amazonaws.com/kfuse/*"
        attestors:
        - entries:
          - keys:
              publicKeys: |
                -----BEGIN PUBLIC KEY-----
                MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEg5MTbws6zhPPlz8EKgcyOX+y2BCd
                bLVOMHCG3FjpS4JGijEcbKJ9gd13lHbWZuZkFk2I3BVZIctOjvrf+BgIgg==
                -----END PUBLIC KEY-----
```

## Troubleshooting
"Access Denied" when using KMS key
**Cause:** Missing IAM permissions
**Solution:** Add KMS permissions (`kms:GetPublicKey`, `kms:Verify`, `kms:DescribeKey`) to your IAM role

"No matching signatures"
**Cause:** Image is not signed or signature was not found
**Solution:** Verify the image tag is correct and check if signature exists:

```bash
aws ecr list-images \
  --repository-name kfuse/ui \
  --region us-west-2 | grep ".sig"
```

"MANIFEST_UNKNOWN"
**Cause:** Image doesn’t exist in ECR
**Solution:** Verify the image reference is correct and image exists

## Security Best Practices
1. **Verify all images** before deployment
2. **Use admission controllers** to enforce verification at deployment time
3. **Monitor verification failures** and alert on unsigned images
4. **Regularly audit** signature coverage across your deployments
5. **Keep cosign updated** to the latest stable version

## Frequently Asked Questions
- **Do I need Kloudfuse’s private key to verify signatures?**
  No. You only need the public key, which is freely available.
- **Can signatures be forged?**
  No. Signatures can only be created with the private key in Kloudfuse’s KMS, which never leaves AWS.
- **What if I can’t access AWS KMS?**
  Use Method 2: Verify Using Public Key File with the exported public key (no AWS access required).
- **Are signatures stored in the image?**
  No. Signatures are stored as separate OCI artifacts in ECR with `.sig` tags.
- **What if Kloudfuse rotates the signing key?**
  Kloudfuse will notify customers, provide the new public key, and sign new images with the new key. Old signatures remain valid.
