|
| 1 | +# Cosign Integration for Drone-Docker |
| 2 | + |
| 3 | +This document describes how to use the cosign container image signing feature in drone-docker. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The drone-docker plugin now supports automatic container image signing using cosign after each successful push. This provides cryptographic verification that images haven't been tampered with. |
| 8 | + |
| 9 | +## Environment Variables |
| 10 | + |
| 11 | +The plugin accepts three cosign-related environment variables: |
| 12 | + |
| 13 | +### `PLUGIN_COSIGN_PRIVATE_KEY` (Required for signing) |
| 14 | +- **Description**: Private key for signing (PEM format content or file path) |
| 15 | +- **Format**: Either PEM content or file path to private key |
| 16 | +- **Usage**: Should be provided via secrets |
| 17 | + |
| 18 | +### `PLUGIN_COSIGN_PASSWORD` (Optional) |
| 19 | +- **Description**: Password for encrypted private keys |
| 20 | +- **Usage**: Only needed if your private key is password-protected |
| 21 | + |
| 22 | +### `PLUGIN_COSIGN_PARAMS` (Optional) |
| 23 | +- **Description**: Additional cosign parameters |
| 24 | +- **Examples**: |
| 25 | + - `-a build_id=123` (add annotations) |
| 26 | + - `--tlog-upload=false` (disable transparency log) |
| 27 | + - `--rekor-url=https://custom-rekor.example.com` (custom rekor instance) |
| 28 | + |
| 29 | +## Usage Examples |
| 30 | + |
| 31 | +### 1. Basic Signing (Drone) |
| 32 | + |
| 33 | +```yaml |
| 34 | +kind: pipeline |
| 35 | +type: docker |
| 36 | +name: default |
| 37 | + |
| 38 | +steps: |
| 39 | +- name: docker |
| 40 | + image: plugins/docker |
| 41 | + settings: |
| 42 | + repo: myregistry/myapp |
| 43 | + tags: latest |
| 44 | + cosign_private_key: |
| 45 | + from_secret: cosign_private_key |
| 46 | + cosign_password: |
| 47 | + from_secret: cosign_password |
| 48 | +``` |
| 49 | +
|
| 50 | +### 2. Advanced Signing with Annotations (Drone) |
| 51 | +
|
| 52 | +```yaml |
| 53 | +steps: |
| 54 | +- name: docker |
| 55 | + image: plugins/docker |
| 56 | + settings: |
| 57 | + repo: myregistry/myapp |
| 58 | + tags: |
| 59 | + - latest |
| 60 | + - ${DRONE_BUILD_NUMBER} |
| 61 | + cosign_private_key: |
| 62 | + from_secret: cosign_private_key |
| 63 | + cosign_params: "-a build_id=${DRONE_BUILD_NUMBER} -a commit_sha=${DRONE_COMMIT_SHA} -a branch=${DRONE_BRANCH}" |
| 64 | +``` |
| 65 | +
|
| 66 | +### 3. Harness CI/CD Usage |
| 67 | +
|
| 68 | +```yaml |
| 69 | +- step: |
| 70 | + type: Plugin |
| 71 | + name: Build and Sign |
| 72 | + identifier: build_and_sign |
| 73 | + spec: |
| 74 | + connectorRef: account.harnessImage |
| 75 | + image: plugins/docker |
| 76 | + settings: |
| 77 | + repo: myregistry/myapp |
| 78 | + tags: <+pipeline.sequenceId> |
| 79 | + cosign_private_key: <+secrets.getValue("cosign_private_key")> |
| 80 | + cosign_password: <+secrets.getValue("cosign_password")> |
| 81 | + cosign_params: "-a harness_build=<+pipeline.sequenceId> -a harness_project=<+project.name>" |
| 82 | +``` |
| 83 | +
|
| 84 | +## Key Management |
| 85 | +
|
| 86 | +### Generating Cosign Keys |
| 87 | +
|
| 88 | +```bash |
| 89 | +# Generate a new key pair |
| 90 | +cosign generate-key-pair |
| 91 | + |
| 92 | +# This creates: |
| 93 | +# - cosign.key (private key) |
| 94 | +# - cosign.pub (public key) |
| 95 | +``` |
| 96 | + |
| 97 | +### Storing Keys Securely |
| 98 | +**Harness Secrets:** |
| 99 | +1. Go to Project Settings → Secrets |
| 100 | +2. Create new secret with type "File" for private key |
| 101 | +3. Create new secret with type "Text" for password |
| 102 | + |
| 103 | +## Security Features |
| 104 | + |
| 105 | +### Automatic Validation |
| 106 | +- ✅ **Private key format validation**: Ensures PEM format is correct |
| 107 | +- ✅ **Password requirement detection**: Warns if encrypted key needs password |
| 108 | +- ✅ **Keyless signing prevention**: Warns that OIDC keyless signing isn't supported |
| 109 | + |
| 110 | +### Error Handling |
| 111 | +- **Invalid private key**: `❌ Invalid private key format. Expected PEM format` |
| 112 | +- **Missing password**: `🔐 Encrypted private key requires password. Set PLUGIN_COSIGN_PASSWORD` |
| 113 | +- **Keyless signing**: `⚠️ WARNING: Keyless signing (OIDC) isn't supported yet in this plugin` |
| 114 | + |
| 115 | +## Signing Behavior |
| 116 | + |
| 117 | +### When Signing Occurs |
| 118 | +- ✅ **After each successful push**: Images are signed immediately after push |
| 119 | +- ✅ **Multiple tags**: Each tag gets signed individually |
| 120 | +- ✅ **Push-only mode**: Works with existing images |
| 121 | +- ✅ **Dry-run respect**: Skips signing in dry-run mode |
| 122 | + |
| 123 | +### Image References |
| 124 | +- **Preferred**: Signs by digest (e.g., `image@sha256:abc123...`) for security |
| 125 | +- **Fallback**: Signs by tag if digest unavailable |
| 126 | + |
| 127 | +### Authentication |
| 128 | +- **Registry auth**: Automatically uses existing Docker registry credentials |
| 129 | + |
| 130 | +## Verification |
| 131 | + |
| 132 | +To verify a signed image: |
| 133 | + |
| 134 | +```bash |
| 135 | +# Verify with public key |
| 136 | +cosign verify --key cosign.pub myregistry/myapp:latest |
| 137 | + |
| 138 | +# Verify with annotations |
| 139 | +cosign verify --key cosign.pub \ |
| 140 | + -a build_id=123 \ |
| 141 | + myregistry/myapp:latest |
| 142 | +``` |
| 143 | + |
| 144 | +## Troubleshooting |
| 145 | + |
| 146 | +### Common Issues |
| 147 | + |
| 148 | +1. **"cosign: command not found"** |
| 149 | + - The container image includes cosign binary |
| 150 | + - Use the latest plugin image: `plugins/docker:latest` |
| 151 | + |
| 152 | +2. **"keyless signing not supported"** |
| 153 | + - This plugin only supports private key signing |
| 154 | + - Don't use `--oidc` or `--identity-token` in `cosign_params` |
| 155 | + |
| 156 | +3. **"encrypted private key requires password"** |
| 157 | + - Set `PLUGIN_COSIGN_PASSWORD` environment variable |
| 158 | + - Or use an unencrypted private key |
| 159 | + |
| 160 | +4. **Registry authentication issues** |
| 161 | + - Cosign uses the same Docker registry credentials |
| 162 | + - Ensure Docker login is working first |
0 commit comments