Skip to content

Commit d77a7e3

Browse files
add package to fetch GitHub Action OIDC tokens
cosign used to do this, but sigstore-go doesn't have any support for ambient credential detection. This was copied from cosign: https://github.com/sigstore/cosign/blob/c6cdf1b37664e8e83fdf4d4abf464f2ead4021a2/pkg/providers/github/github.go Signed-off-by: Spencer Schrock <sschrock@google.com>
1 parent ee561a8 commit d77a7e3

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed

internal/oidc/oidc.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright 2025 OpenSSF Authors
2+
// Copyright 2021 The Sigstore Authors.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
// SPDX-License-Identifier: Apache-2.0
17+
18+
// Package oidc provides functionality to get an OIDC token from github.
19+
package oidc
20+
21+
import (
22+
"context"
23+
"encoding/json"
24+
"fmt"
25+
"net/http"
26+
"os"
27+
"strings"
28+
"time"
29+
)
30+
31+
const (
32+
envRequestURL = "ACTIONS_ID_TOKEN_REQUEST_URL"
33+
envRequestToken = "ACTIONS_ID_TOKEN_REQUEST_TOKEN"
34+
)
35+
36+
func RequestToken(ctx context.Context) (string, error) {
37+
url := os.Getenv(envRequestURL) + "&audience=sigstore"
38+
39+
req, err := http.NewRequest(http.MethodGet, url, nil)
40+
if err != nil {
41+
return "", err
42+
}
43+
44+
// May be replaced by a different client if we hit HTTP_1_1_REQUIRED.
45+
client := http.DefaultClient
46+
47+
// Retry up to 3 times.
48+
for i := 0; ; i++ {
49+
req.Header.Add("Authorization", "bearer "+os.Getenv(envRequestToken))
50+
resp, err := client.Do(req)
51+
if err != nil {
52+
if i == 2 {
53+
return "", err
54+
}
55+
56+
// This error isn't exposed by net/http, and retrying this with the
57+
// DefaultClient will fail because it will just use HTTP2 again.
58+
// I don't know why go doesn't do this for us.
59+
if strings.Contains(err.Error(), "HTTP_1_1_REQUIRED") {
60+
http1transport := http.DefaultTransport.(*http.Transport).Clone()
61+
http1transport.ForceAttemptHTTP2 = false
62+
63+
client = &http.Client{
64+
Transport: http1transport,
65+
}
66+
}
67+
68+
fmt.Fprintf(os.Stderr, "error fetching GitHub OIDC token (will retry): %v\n", err)
69+
time.Sleep(time.Second)
70+
continue
71+
}
72+
defer resp.Body.Close()
73+
74+
var payload struct {
75+
Value string `json:"value"`
76+
}
77+
decoder := json.NewDecoder(resp.Body)
78+
if err := decoder.Decode(&payload); err != nil {
79+
return "", err
80+
}
81+
return payload.Value, nil
82+
}
83+
}

0 commit comments

Comments
 (0)