1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
|
// Copyright The Notary Project Authors.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package command
import (
"fmt"
"path/filepath"
"time"
. "github.com/notaryproject/notation/test/e2e/internal/notation"
"github.com/notaryproject/notation/test/e2e/internal/utils"
. "github.com/notaryproject/notation/test/e2e/suite/common"
. "github.com/onsi/ginkgo/v2"
)
var _ = Describe("notation sign", func() {
It("by digest", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.Exec("sign", artifact.ReferenceWithDigest()).
MatchKeyWords(SignSuccessfully)
OldNotation().WithDescription("verify by digest").
Exec("verify", artifact.ReferenceWithDigest()).
MatchKeyWords(VerifySuccessfully)
OldNotation().WithDescription("verify by tag").
Exec("verify", artifact.ReferenceWithTag()).
MatchKeyWords(VerifySuccessfully)
})
})
It("by digest with COSE format", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.Exec("sign", "--signature-format", "cose", artifact.ReferenceWithDigest()).
MatchKeyWords(SignSuccessfully)
OldNotation().WithDescription("verify by digest").
Exec("verify", artifact.ReferenceWithTag()).
MatchKeyWords(VerifySuccessfully)
OldNotation().WithDescription("verify by tag").
Exec("verify", artifact.ReferenceWithTag()).
MatchKeyWords(VerifySuccessfully)
})
})
It("by tag with JWS format", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.WithDescription("sign with JWS").
Exec("sign", artifact.ReferenceWithTag(), "--signature-format", "jws").
MatchKeyWords(SignSuccessfully)
OldNotation().WithDescription("verify JWS signature").
Exec("verify", artifact.ReferenceWithTag()).
MatchKeyWords(VerifySuccessfully)
})
})
It("by tag with COSE signature format", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.WithDescription("sign with COSE").
Exec("sign", artifact.ReferenceWithTag(), "--signature-format", "cose").
MatchKeyWords(SignSuccessfully)
OldNotation().WithDescription("verify COSE signature").
Exec("verify", artifact.ReferenceWithTag()).
MatchKeyWords(VerifySuccessfully)
})
})
It("with force-referrers-tag set", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.WithDescription("store signature with referrers tag schema").
Exec("sign", artifact.ReferenceWithDigest(), "--force-referrers-tag").
MatchKeyWords(SignSuccessfully)
OldNotation().WithDescription("verify by tag schema").
Exec("verify", artifact.ReferenceWithDigest(), "-v").
MatchKeyWords(VerifySuccessfully)
})
})
It("with force-referrers-tag set to false", func() {
Host(BaseOptionsWithExperimental(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.WithDescription("store signature with Referrers API").
Exec("sign", artifact.ReferenceWithDigest(), "--force-referrers-tag=false").
MatchKeyWords(SignSuccessfully)
OldNotation(BaseOptionsWithExperimental()...).WithDescription("verify by referrers api").
Exec("verify", artifact.ReferenceWithDigest(), "--allow-referrers-api", "-v").
MatchKeyWords(VerifySuccessfully)
})
})
It("with allow-referrers-api set", func() {
Host(BaseOptionsWithExperimental(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.WithDescription("store signature with Referrers API").
Exec("sign", artifact.ReferenceWithDigest(), "--allow-referrers-api").
MatchErrKeyWords(
"Warning: This feature is experimental and may not be fully tested or completed and may be deprecated.",
"Warning: flag '--allow-referrers-api' is deprecated and will be removed in future versions, use '--force-referrers-tag=false' instead.",
).
MatchKeyWords(SignSuccessfully)
OldNotation(BaseOptionsWithExperimental()...).WithDescription("verify by referrers api").
Exec("verify", artifact.ReferenceWithDigest(), "--allow-referrers-api", "-v").
MatchKeyWords(VerifySuccessfully)
})
})
It("with allow-referrers-api set to false", func() {
Host(BaseOptionsWithExperimental(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.WithDescription("store signature with referrers tag schema").
Exec("sign", artifact.ReferenceWithDigest(), "--allow-referrers-api=false").
MatchErrKeyWords(
"Warning: This feature is experimental and may not be fully tested or completed and may be deprecated.",
"Warning: flag '--allow-referrers-api' is deprecated and will be removed in future versions.",
).
MatchKeyWords(SignSuccessfully)
OldNotation().WithDescription("verify by tag schema").
Exec("verify", artifact.ReferenceWithDigest(), "-v").
MatchKeyWords(VerifySuccessfully)
})
})
It("with both force-referrers-tag and allow-referrers-api set", func() {
Host(BaseOptionsWithExperimental(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.WithDescription("store signature with Referrers API").
ExpectFailure().
Exec("sign", artifact.ReferenceWithDigest(), "--force-referrers-tag", "--allow-referrers-api").
MatchErrKeyWords(
"Warning: This feature is experimental and may not be fully tested or completed and may be deprecated.",
"[allow-referrers-api force-referrers-tag] were all set",
)
})
})
It("with allow-referrers-api set and experimental off", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.WithDescription("store signature with Referrers API").
ExpectFailure().
Exec("sign", artifact.ReferenceWithDigest(), "--allow-referrers-api").
MatchErrKeyWords(
"Error: flag(s) --allow-referrers-api in \"notation sign\" is experimental and not enabled by default.")
})
})
It("with specific key", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
const keyName = "sKey"
notation.Exec("cert", "generate-test", keyName).
MatchKeyWords(fmt.Sprintf("notation/localkeys/%s.crt", keyName))
notation.Exec("sign", "--key", keyName, artifact.ReferenceWithDigest()).
MatchKeyWords(SignSuccessfully)
// copy the generated cert file and create the new trust policy for verify signature with generated new key.
OldNotation(AuthOption("", ""),
AddTrustStoreOption(keyName, vhost.AbsolutePath(NotationDirName, LocalKeysDirName, keyName+".crt")),
AddTrustPolicyOption("generate_test_trustpolicy.json"),
).Exec("verify", artifact.ReferenceWithTag()).
MatchKeyWords(VerifySuccessfully)
})
})
It("with expiry in 24h", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.Exec("sign", "--expiry", "24h", artifact.ReferenceWithDigest()).
MatchKeyWords(SignSuccessfully)
OldNotation().Exec("verify", artifact.ReferenceWithTag()).
MatchKeyWords(VerifySuccessfully)
})
})
It("with expiry in 2s", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.Exec("sign", "--expiry", "2s", artifact.ReferenceWithDigest()).
MatchKeyWords(SignSuccessfully)
// sleep to wait for expiry
time.Sleep(2100 * time.Millisecond)
OldNotation().ExpectFailure().Exec("verify", artifact.ReferenceWithDigest(), "-v").
MatchErrKeyWords("expiry validation failed.").
MatchErrKeyWords("signature verification failed for all the signatures")
})
})
It("by digest with oci layout", func() {
HostWithOCILayout(BaseOptionsWithExperimental(), func(notation *utils.ExecOpts, ociLayout *OCILayout, vhost *utils.VirtualHost) {
notation.Exec("sign", "--oci-layout", ociLayout.ReferenceWithDigest()).
MatchKeyWords(SignSuccessfully)
})
})
It("by digest with oci layout and COSE format", func() {
HostWithOCILayout(BaseOptionsWithExperimental(), func(notation *utils.ExecOpts, ociLayout *OCILayout, vhost *utils.VirtualHost) {
notation.Exec("sign", "--oci-layout", "--signature-format", "cose", ociLayout.ReferenceWithDigest()).
MatchKeyWords(SignSuccessfully)
})
})
It("by tag with oci layout", func() {
HostWithOCILayout(BaseOptionsWithExperimental(), func(notation *utils.ExecOpts, ociLayout *OCILayout, vhost *utils.VirtualHost) {
notation.Exec("sign", "--oci-layout", ociLayout.ReferenceWithDigest()).
MatchKeyWords(SignSuccessfully)
})
})
It("by tag with oci layout and COSE format", func() {
HostWithOCILayout(BaseOptionsWithExperimental(), func(notation *utils.ExecOpts, ociLayout *OCILayout, vhost *utils.VirtualHost) {
notation.Exec("sign", "--oci-layout", "--signature-format", "cose", ociLayout.ReferenceWithDigest()).
MatchKeyWords(SignSuccessfully)
})
})
It("by digest with oci layout but without experimental", func() {
HostWithOCILayout(BaseOptions(), func(notation *utils.ExecOpts, ociLayout *OCILayout, vhost *utils.VirtualHost) {
expectedErrMsg := "Error: flag(s) --oci-layout in \"notation sign\" is experimental and not enabled by default. To use, please set NOTATION_EXPERIMENTAL=1 environment variable\n"
notation.ExpectFailure().Exec("sign", "--oci-layout", ociLayout.ReferenceWithDigest()).
MatchErrContent(expectedErrMsg)
})
})
It("with TLS by digest", func() {
HostInGithubAction(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.Exec("sign", "-d", artifact.DomainReferenceWithDigest()).
MatchKeyWords(SignSuccessfully).
MatchErrKeyWords(HTTPSRequest).
NoMatchErrKeyWords(HTTPRequest)
OldNotation().Exec("verify", artifact.DomainReferenceWithDigest()).
MatchKeyWords(VerifySuccessfully)
})
})
It("with --insecure-registry by digest", func() {
HostInGithubAction(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.Exec("sign", "-d", "--insecure-registry", artifact.DomainReferenceWithDigest()).
MatchKeyWords(SignSuccessfully).
MatchErrKeyWords(HTTPRequest).
NoMatchErrKeyWords(HTTPSRequest)
OldNotation().Exec("verify", artifact.DomainReferenceWithDigest()).
MatchKeyWords(VerifySuccessfully)
})
})
It("with timestamping", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.Exec("sign", "--timestamp-url", "http://rfc3161timestamp.globalsign.com/advanced", "--timestamp-root-cert", filepath.Join(NotationE2EConfigPath, "timestamp", "globalsignTSARoot.cer"), artifact.ReferenceWithDigest()).
MatchKeyWords(SignSuccessfully)
})
})
It("with timestamp-root-cert but no timestamp-url", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.ExpectFailure().Exec("sign", "--timestamp-root-cert", filepath.Join(NotationE2EConfigPath, "timestamp", "globalsignTSARoot.cer"), artifact.ReferenceWithDigest()).
MatchErrKeyWords("Error: if any flags in the group [timestamp-url timestamp-root-cert] are set they must all be set; missing [timestamp-url]")
})
})
It("with timestamp-url but no timestamp-root-cert", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.ExpectFailure().Exec("sign", "--timestamp-url", "http://rfc3161timestamp.globalsign.com/advanced", artifact.ReferenceWithDigest()).
MatchErrKeyWords("Error: if any flags in the group [timestamp-url timestamp-root-cert] are set they must all be set; missing [timestamp-root-cert]")
})
})
It("with timestamping and empty tsa server", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.ExpectFailure().Exec("sign", "--timestamp-url", "", "--timestamp-root-cert", filepath.Join(NotationE2EConfigPath, "timestamp", "globalsignTSARoot.cer"), artifact.ReferenceWithDigest()).
MatchErrKeyWords("Error: timestamping: tsa url cannot be empty")
})
})
It("with timestamping and empty tsa root cert", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.ExpectFailure().Exec("sign", "--timestamp-url", "dummy", "--timestamp-root-cert", "", artifact.ReferenceWithDigest()).
MatchErrKeyWords("Error: timestamping: tsa root certificate path cannot be empty")
})
})
It("with timestamping and invalid tsa server", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.ExpectFailure().Exec("sign", "--timestamp-url", "http://invalid.com", "--timestamp-root-cert", filepath.Join(NotationE2EConfigPath, "timestamp", "globalsignTSARoot.cer"), artifact.ReferenceWithDigest()).
MatchErrKeyWords("Error: timestamp: Post \"http://invalid.com\"").
MatchErrKeyWords("no such host")
})
})
It("with timestamping and invalid tsa root certificate", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.ExpectFailure().Exec("sign", "--timestamp-url", "http://timestamp.digicert.com", "--timestamp-root-cert", filepath.Join(NotationE2EConfigPath, "timestamp", "invalid.crt"), artifact.ReferenceWithDigest()).
MatchErrKeyWords("Error: x509: malformed certificate")
})
})
It("with timestamping and empty tsa root certificate file", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.ExpectFailure().Exec("sign", "--timestamp-url", "http://timestamp.digicert.com", "--timestamp-root-cert", filepath.Join(NotationE2EConfigPath, "timestamp", "Empty.txt"), artifact.ReferenceWithDigest()).
MatchErrKeyWords("cannot find any certificate from").
MatchErrKeyWords("Expecting single x509 root certificate in PEM or DER format from the file")
})
})
It("with timestamping and more than one certificates in tsa root certificate file", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.ExpectFailure().Exec("sign", "--timestamp-url", "http://timestamp.digicert.com", "--timestamp-root-cert", filepath.Join(NotationE2EConfigPath, "timestamp", "CertChain.pem"), artifact.ReferenceWithDigest()).
MatchErrKeyWords("found more than one certificates").
MatchErrKeyWords("Expecting single x509 root certificate in PEM or DER format from the file")
})
})
It("with timestamping and intermediate certificate file", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.ExpectFailure().Exec("sign", "--timestamp-url", "http://timestamp.digicert.com", "--timestamp-root-cert", filepath.Join(NotationE2EConfigPath, "timestamp", "intermediate.pem"), artifact.ReferenceWithDigest()).
MatchErrKeyWords("failed to check root certificate with error: crypto/rsa: verification error")
})
})
It("with timestamping and not self-issued certificate file", func() {
Host(BaseOptions(), func(notation *utils.ExecOpts, artifact *Artifact, vhost *utils.VirtualHost) {
notation.ExpectFailure().Exec("sign", "--timestamp-url", "http://timestamp.digicert.com", "--timestamp-root-cert", filepath.Join(NotationE2EConfigPath, "timestamp", "notSelfIssued.crt"), artifact.ReferenceWithDigest()).
MatchErrKeyWords("is not a root certificate. Expecting single x509 root certificate in PEM or DER format from the file")
})
})
})
|