Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions .github/workflows/create-releases.yml
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ jobs:
needs.runtime_compatibility.result == 'success'
permissions:
contents: read
id-token: write
attestations: write
runs-on: ${{ vars.SDK_GHA_RUNNER || 'ubuntu-24.04' }}
timeout-minutes: 90
environment: publish
Expand Down Expand Up @@ -316,6 +318,103 @@ jobs:
exit 1
fi

- name: Build Maven artifacts for provenance
id: maven-artifacts
env:
RELEASE_TAG: ${{ needs.release.outputs.release_tag }}
SOURCE_SHA: ${{ needs.release.outputs.source_sha }}
run: |
set -euo pipefail

if [[ ! "$SOURCE_SHA" =~ ^[0-9a-f]{40}$ ||
"$SOURCE_SHA" != "$(git rev-parse HEAD)" ]]; then
echo "::error::The checked-out source does not match the verified release SHA"
exit 1
fi
if [[ ! "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]]; then
echo "::error::Invalid verified release tag"
exit 1
fi

version="${RELEASE_TAG#v}"
tasks=()
subjects=()
for artifact in $MAVEN_ARTIFACTS; do
tasks+=(":$artifact:jar")
subjects+=("$artifact/build/libs/$artifact-$version.jar")
done

./gradlew "${tasks[@]}" --no-configuration-cache

for subject in "${subjects[@]}"; do
if [[ ! -f "$subject" || -L "$subject" ]]; then
echo "::error::Missing or unsafe Maven artifact: $subject"
exit 1
fi
done

sha256sum "${subjects[@]}" > "$RUNNER_TEMP/maven-artifact-provenance.sha256"

workflow_path="${GITHUB_WORKFLOW_REF#"$GITHUB_REPOSITORY/"}"
workflow_path="${workflow_path%@*}"
jq -n \
--arg repository "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY" \
--arg workflow_ref "$GITHUB_REF" \
--arg workflow_path "$workflow_path" \
--arg workflow_identity "$GITHUB_SERVER_URL/$GITHUB_WORKFLOW_REF" \
--arg event_name "$GITHUB_EVENT_NAME" \
--arg repository_id "$GITHUB_REPOSITORY_ID" \
--arg repository_owner_id "$GITHUB_REPOSITORY_OWNER_ID" \
--arg runner_environment "$RUNNER_ENVIRONMENT" \
--arg source_sha "$SOURCE_SHA" \
--arg release_tag "$RELEASE_TAG" \
--arg invocation_id \
"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID/attempts/$GITHUB_RUN_ATTEMPT" \
'{
buildDefinition: {
buildType: "https://actions.github.io/buildtypes/workflow/v1",
externalParameters: {
workflow: {
ref: $workflow_ref,
repository: $repository,
path: $workflow_path
}
},
internalParameters: {
github: {
event_name: $event_name,
repository_id: $repository_id,
repository_owner_id: $repository_owner_id,
runner_environment: $runner_environment
}
},
resolvedDependencies: [
{
uri: ("git+" + $repository + "@refs/tags/" + $release_tag),
digest: { gitCommit: $source_sha }
}
]
},
runDetails: {
builder: { id: $workflow_identity },
metadata: { invocationId: $invocation_id }
}
}' > "$RUNNER_TEMP/maven-release-provenance.json"

{
echo 'subject_paths<<EOF'
printf '%s\n' "${subjects[@]}"
echo EOF
echo "predicate_path=$RUNNER_TEMP/maven-release-provenance.json"
} >> "$GITHUB_OUTPUT"

- name: Attest Maven artifact provenance
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
Comment thread
HAYDEN-OAI marked this conversation as resolved.
with:
subject-path: ${{ steps.maven-artifacts.outputs.subject_paths }}
predicate-type: https://slsa.dev/provenance/v1
predicate-path: ${{ steps.maven-artifacts.outputs.predicate_path }}

- name: Publish to Maven Central
env:
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.OPENAI_SONATYPE_USERNAME }}
Expand Down Expand Up @@ -349,10 +448,20 @@ jobs:
fi
export GPG_SIGNING_KEY_ID

publish_exclusions=()
for artifact in $MAVEN_ARTIFACTS; do
publish_exclusions+=("--exclude-task" ":$artifact:jar")
done

sha256sum --check "$RUNNER_TEMP/maven-artifact-provenance.sha256"
./gradlew publishAndReleaseToMavenCentral \
"${publish_exclusions[@]}" \
--stacktrace \
--no-configuration-cache

- name: Verify attested Maven artifacts
Comment thread
HAYDEN-OAI marked this conversation as resolved.
run: sha256sum --check "$RUNNER_TEMP/maven-artifact-provenance.sha256"

- name: Wait for Maven Central
env:
RELEASE_TAG: ${{ needs.release.outputs.release_tag }}
Expand Down
18 changes: 18 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,24 @@ Please give the maintainers a reasonable opportunity to investigate and address

Thank you for helping us keep this SDK and the systems it interacts with secure.

## Maven Artifact Provenance

Official Maven Central releases include GitHub artifact attestations for the
`openai-java`, `openai-java-core`, `openai-java-client-okhttp`, and
`openai-java-bedrock` binary JARs. Each attestation binds an artifact's digest to
the trusted release workflow, source repository, and commit using short-lived
GitHub OpenID Connect credentials.

After downloading a published JAR from Maven Central, verify its provenance with:

```sh
gh attestation verify path/to/openai-java-VERSION.jar -R openai/openai-java
```

Maven Central separately requires a publisher token and PGP signatures. Those
credentials remain restricted to the `main`-only publishing environment and are
not exposed to the attestation action.

## Gradle Build Cache Trust

The Kotlin Gradle plugin used to build this SDK is affected by
Expand Down
Loading
Loading