Skip to content

Commit

Permalink
Use SOURCE_DATE_EPOCH for OCI CreatedAt times (#2878)
Browse files Browse the repository at this point in the history
Using time.Now() makes this unreproducible and causes a lot of churn
when re-running the same command.

Signed-off-by: Jon Johnson <[email protected]>
  • Loading branch information
jonjohnsonjr authored Apr 7, 2023
1 parent 8faaee4 commit de03ebb
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 5 deletions.
38 changes: 38 additions & 0 deletions internal/pkg/now/now.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// Copyright 2023 The Sigstore 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 now

import (
"fmt"
"os"
"strconv"
"time"
)

// Now returns SOURCE_DATE_EPOCH or time.Now().
func Now() (time.Time, error) {
// nolint
epoch := os.Getenv("SOURCE_DATE_EPOCH")
if epoch == "" {
return time.Now(), nil
}

seconds, err := strconv.ParseInt(epoch, 10, 64)
if err != nil {
return time.Now(), fmt.Errorf("SOURCE_DATE_EPOCH should be the number of seconds since January 1st 1970, 00:00 UTC, got: %w", err)
}
return time.Unix(seconds, 0), nil
}
7 changes: 7 additions & 0 deletions pkg/cosign/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const (
VariableBuildkiteAgentEndpoint Variable = "BUILDKITE_AGENT_ENDPOINT"
VariableBuildkiteJobID Variable = "BUILDKITE_JOB_ID"
VariableBuildkiteAgentLogLevel Variable = "BUILDKITE_AGENT_LOG_LEVEL"
VariableSourceDateEpoch Variable = "SOURCE_DATE_EPOCH"
)

var (
Expand Down Expand Up @@ -204,6 +205,12 @@ var (
Sensitive: true,
External: true,
},
VariableSourceDateEpoch: {
Description: "overrides current time for reproducible builds, see https://reproducible-builds.org/docs/source-date-epoch/",
Expects: "number of seconds since unix epoch",
Sensitive: false,
External: true,
},
}
)

Expand Down
10 changes: 7 additions & 3 deletions pkg/oci/mutate/signatures.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
package mutate

import (
"time"

v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/sigstore/cosign/v2/internal/pkg/now"
"github.com/sigstore/cosign/v2/pkg/oci"
)

Expand All @@ -44,8 +43,13 @@ func AppendSignatures(base oci.Signatures, sigs ...oci.Signature) (oci.Signature
return nil, err
}

t, err := now.Now()
if err != nil {
return nil, err
}

// Set the Created date to time of execution
img, err = mutate.CreatedAt(img, v1.Time{Time: time.Now()})
img, err = mutate.CreatedAt(img, v1.Time{Time: t})
if err != nil {
return nil, err
}
Expand Down
9 changes: 7 additions & 2 deletions pkg/oci/static/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ package static

import (
"io"
"time"

v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/google/go-containerregistry/pkg/v1/types"
"github.com/sigstore/cosign/v2/internal/pkg/now"
"github.com/sigstore/cosign/v2/pkg/oci"
"github.com/sigstore/cosign/v2/pkg/oci/signed"
)
Expand All @@ -49,8 +49,13 @@ func NewFile(payload []byte, opts ...Option) (oci.File, error) {
// Add annotations from options
img = mutate.Annotations(img, o.Annotations).(v1.Image)

t, err := now.Now()
if err != nil {
return nil, err
}

// Set the Created date to time of execution
img, err = mutate.CreatedAt(img, v1.Time{Time: time.Now()})
img, err = mutate.CreatedAt(img, v1.Time{Time: t})
if err != nil {
return nil, err
}
Expand Down

0 comments on commit de03ebb

Please sign in to comment.