Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Readability fixes for KubeCon NA '23 demo #16

Merged
merged 4 commits into from
Nov 2, 2023
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
6 changes: 3 additions & 3 deletions .github/actions/scai-gen-assert/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ runs:

- name: Generate ResourceDescriptor for evidence
id: gen-rd
uses: ./.github/actions/scai-gen-rd
# change to v0.2 tag when released
uses: in-toto/scai-demos/.github/actions/scai-gen-rd@main
with:
name: "${{ inputs.evidence-file }}"
path: "${{ inputs.evidence-path }}"
Expand All @@ -54,6 +55,5 @@ runs:
id: scai-gen-assert
shell: bash
run: |
mkdir -p ${{ inputs.assertion-path }}
scai-gen assert -e ${{ steps.gen-rd.outputs.file-rd-name }} -o ${{ inputs.assertion-path }}/${{ inputs.assertion-name }} ${{ inputs.attribute}}
scai-gen assert --evidence ${{ steps.gen-rd.outputs.file-rd-name }} --out-file ${{ inputs.assertion-path }}/${{ inputs.assertion-name }} ${{ inputs.attribute}}
echo "assertion-name=${{ inputs.assertion-path }}/${{ inputs.assertion-name }}" >> "$GITHUB_OUTPUT"
6 changes: 2 additions & 4 deletions .github/actions/scai-gen-rd/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,13 @@ runs:
if: ${{ inputs.is-file == 'true' }}
shell: bash
run: |
mkdir -p ${{ inputs.rd-path }}
scai-gen rd file -n ${{ inputs.name }} -l ${{ inputs.location }} -t ${{ inputs.media-type }} -o ${{ inputs.rd-path }}/${{ inputs.rd-name }} ${{ inputs.path }}/${{ inputs.name }}
scai-gen rd file --name ${{ inputs.name }} --download-location ${{ inputs.location }} --media-type ${{ inputs.media-type }} --out-file ${{ inputs.rd-path }}/${{ inputs.rd-name }} ${{ inputs.path }}/${{ inputs.name }}
echo "rd-name=${{ inputs.rd-path }}/${{ inputs.rd-name }}" >> "$GITHUB_OUTPUT"

- name: Run scai-gen rd remote
id: scai-gen-rd-remote
if: ${{ inputs.is-file == 'false' }}
shell: bash
run: |
mkdir -p ${{ inputs.rd-path }}
scai-gen rd remote -n ${{ inputs.name }} -d ${{ inputs.digest }} -g ${{ inputs.hash-alg }} -o ${{ inputs.rd-path }}/${{ inputs.rd-name }} ${{ inputs.uri }}
scai-gen rd remote --name ${{ inputs.name }} --digest ${{ inputs.digest }} --hash-alg ${{ inputs.hash-alg }} --out-file ${{ inputs.rd-path }}/${{ inputs.rd-name }} ${{ inputs.uri }}
echo "rd-name=${{ inputs.rd-path }}/${{ inputs.rd-name }}" >> "$GITHUB_OUTPUT"
4 changes: 1 addition & 3 deletions .github/actions/scai-gen-report/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@ runs:
id: scai-gen-report
shell: bash
run: |
mkdir -p ${{ inputs.report-path }}
scai-gen report -s ${{ inputs.subject }} -o ${{ inputs.report-path }}/${{ inputs.report-name }} ${{ inputs.attr-assertions }}
scai-gen report --subject ${{ inputs.subject }} --out-file ${{ inputs.report-path }}/${{ inputs.report-name }} --pretty-print ${{ inputs.attr-assertions }}
echo "report-name=${{ inputs.report-path }}/${{ inputs.report-name }}" >> "$GITHUB_OUTPUT"
ls ${{ inputs.report-path }}

- name: Upload the signed SCAI AttributeReport
id: upload-assert
Expand Down
3 changes: 1 addition & 2 deletions .github/actions/scai-gen-sigstore/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ runs:
id: sign
shell: bash
run: |
mkdir -p ${{ inputs.attestation-path }}
scai-gen sigstore -o ${{ inputs.attestation-path}}/${{ inputs.attestation-name }} ${{ inputs.statement-path }}/${{ inputs.statement-name }}
scai-gen sigstore --out-file ${{ inputs.attestation-path}}/${{ inputs.attestation-name }} ${{ inputs.statement-path }}/${{ inputs.statement-name }}
echo "attestation-name=${{ inputs.attestation-path }}/${{ inputs.attestation-name }}" >> "$GITHUB_OUTPUT"

- name: Save the signed in-toto Attestation
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,19 @@ for Python and Go environments.
We encourage you to gain a basic understanding of the [SCAI specification]
before using the scai-generator CLI tools in this repo.

For a full demo of how to use the Go [scai-gen](scai-gen/) tools, read our
[KubeCon + CloudNativeCon NA '23 doc].

## Disclaimer

While the tools in this repo are conformant to the
[in-toto Attestation Framework], they do not generate **authenticated** SCAI
attestations. The example use cases in this repo are only provided for
illustrative purposes.
illustrative purposes, and should not be used in production.

[in-toto Attestation Framework]: https://github.com/in-toto/attestation/tree/main/spec
[intro doc]: docs/intro.md
[KubeCon + CloudNativeCon NA '23]: docs/kccncna2023.md
[usage doc]: docs/usage.md
[SCAI specification]: https://github.com/in-toto/attestation/blob/main/spec/predicates/scai.md
[SCAI spec doc]: https://arxiv.org/pdf/2210.05813.pdf
Binary file added docs/images/intoto-kccncna2023-demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions docs/kccncna2023.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# KubeCon + CloudNativeCon NA '23 Demo

As part of the [in-toto Maintainer Track talk] at KubeCon + CloudNativeCon NA
'23, we present a demo of the in-toto Attestation Framework, SCAI, and the
in-toto Attestation Verifier.

## Demo Setup

The overall flow implemented in the demo is as follows:

<img src="./images/intoto-kccncna2023-demo.png" alt="in-toto demo flow" width="600">

This demo setup is implemented using the [scai-gen GitHub Actions] in a Docker
container build [demo workflow] for the Hyperledger Labs Private Data Objects
project.

### Generated Attestations

This demo generates the follow _authenticated_ in-toto attestations:

* [SLSA Provenance] attestation for the container build
* [SCAI Attribute Report] attestation for additional integrity metadata about
the build

These two attestations are signed using cosign OIDC-based keyless signing,
and uploaded to the public Rekor log.

### Additional Tools

This demo makes use of the following additional tools:

* in-toto [attestation-verifier]
* [Anchore SBOM generator] GitHub Action
* [SLSA generic Provenance generator] GitHub Action
* [strace] Linux syscall tracer

[Anchore SBOM generator]: https://github.com/anchore/sbom-action
[attestation-verifier]: https://github.com/in-toto/attestation-verifier
[demo workflow]: https://github.com/marcelamelara/private-data-objects/blob/intoto-kccncna2023-demo/.github/workflows/intoto-kccncna2023-demo.yml
[in-toto Maintainer Track talk]: https://kccncna2023.sched.com/event/1R2mx
[SLSA generic Provenance generator]: https://github.com/slsa-framework/slsa-github-generator
[SLSA Provenance]: https://github.com/in-toto/attestation/blob/main/spec/predicates/provenance.md
[SCAI Attribute Report]: https://github.com/in-toto/attestation/blob/main/spec/predicates/scai.md
[scai-gen GitHub Actions]: https://github.com/in-toto/scai-demos/tree/main/.github/actions
[strace]: https://strace.io/
7 changes: 6 additions & 1 deletion scai-gen/cmd/assert.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ func init() {
}

func genAttrAssertion(_ *cobra.Command, args []string) error {
// want to make sure the AttributeAssertion is a JSON file
if !fileio.HasJSONExt(outFile) {
return fmt.Errorf("expected a .json extension for the generated SCAI AttributeAssertion file %s", outFile)
}

attribute := args[0]

var target *ita.ResourceDescriptor
Expand Down Expand Up @@ -101,5 +106,5 @@ func genAttrAssertion(_ *cobra.Command, args []string) error {
return fmt.Errorf("invalid SCAI attribute assertion: %w", err)
}

return fileio.WritePbToFile(aa, outFile)
return fileio.WritePbToFile(aa, outFile, false)
}
22 changes: 12 additions & 10 deletions scai-gen/cmd/rd.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,6 @@ func init() {
"The URI of the resource",
)

rdFileCmd.Flags().BoolVarP(
&withContent,
"content",
"c",
false,
"Flag to include the content of the file",
)

rdFileCmd.Flags().StringVarP(
&downloadLocation,
"download-location",
Expand Down Expand Up @@ -165,6 +157,11 @@ func readAnnotations(filename string) (*structpb.Struct, error) {
}

func genRdFromFile(_ *cobra.Command, args []string) error {
// want to make sure the ResourceDescriptor is a JSON file
if !fileio.HasJSONExt(outFile) {
return fmt.Errorf("expected a .json extension for the generated ResourceDescriptor file %s", outFile)
}

filename := args[0]
fileBytes, err := os.ReadFile(filename)
if err != nil {
Expand Down Expand Up @@ -203,10 +200,15 @@ func genRdFromFile(_ *cobra.Command, args []string) error {
return fmt.Errorf("invalid resource descriptor: %w", err)
}

return fileio.WritePbToFile(rd, outFile)
return fileio.WritePbToFile(rd, outFile, false)
}

func genRdForRemote(_ *cobra.Command, args []string) error {
// want to make sure the ResourceDescriptor is a JSON file
if !fileio.HasJSONExt(outFile) {
return fmt.Errorf("expected a .json extension for the generated ResourceDescriptor file %s", outFile)
}

remoteURI := args[0]

digestSet := make(map[string]string)
Expand Down Expand Up @@ -240,5 +242,5 @@ func genRdForRemote(_ *cobra.Command, args []string) error {
return fmt.Errorf("invalid resource descriptor: %w", err)
}

return fileio.WritePbToFile(rd, outFile)
return fileio.WritePbToFile(rd, outFile, false)
}
15 changes: 14 additions & 1 deletion scai-gen/cmd/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,22 @@ func init() {
"",
"The filename of the JSON-encoded producer resource descriptor",
)

reportCmd.Flags().BoolVarP(
&prettyPrint,
"pretty-print",
"y",
false,
"Flag to JSON pretty-print the generated Report",
)
}

func genAttrReport(_ *cobra.Command, args []string) error {
// want to make sure the Report is a JSON file
if !fileio.HasJSONExt(outFile) {
return fmt.Errorf("expected a .json extension for the generated in-toto Statement file %s", outFile)
}

attrAsserts := make([]*scai.AttributeAssertion, 0, len(args))
for _, attrAssertPath := range args {
aa := &scai.AttributeAssertion{}
Expand Down Expand Up @@ -117,5 +130,5 @@ func genAttrReport(_ *cobra.Command, args []string) error {
return fmt.Errorf("invalid in-toto Statement: %w", err)
}

return fileio.WritePbToFile(statement, outFile)
return fileio.WritePbToFile(statement, outFile, prettyPrint)
}
5 changes: 4 additions & 1 deletion scai-gen/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ var rootCmd = &cobra.Command{
Short: "A CLI tool for generating/checking SCAI metadata",
}

var outFile string
var (
outFile string
prettyPrint bool
)

func init() {
rootCmd.AddCommand(rdCmd)
Expand Down
5 changes: 5 additions & 0 deletions scai-gen/cmd/sigstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ func getNewFulcioSigner(ctx context.Context) (*fulcio.Signer, error) {
func signWithSigstore(cmd *cobra.Command, args []string) error {
fmt.Println("EXPERIMENTAL FEATURE. DO NOT USE IN PRODUCTION.")

// want to make sure the DSSE is a JSON file
if !fileio.HasJSONExt(outFile) {
return fmt.Errorf("expected a .json extension for the generated DSSE file %s", outFile)
}

statementFile := args[0]
statement := &ita.Statement{}
err := fileio.ReadPbFromFile(statementFile, statement)
Expand Down
17 changes: 17 additions & 0 deletions scai-gen/fileio/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fileio

import (
"os"
"path/filepath"
"strings"
)

func HasJSONExt(filename string) bool {
return strings.HasSuffix(filename, ".json")
}

func CreateOutDir(filename string) error {
outDir := filepath.Dir(filename)

return os.MkdirAll(outDir, 0644)
adityasaky marked this conversation as resolved.
Show resolved Hide resolved
}
5 changes: 5 additions & 0 deletions scai-gen/fileio/dsse.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,10 @@ func ReadStatementFromDSSEFile(path string) (*ita.Statement, error) {
}

func WriteDSSEToFile(envBytes []byte, outFile string) error {
// ensure the out directory exists
if err := CreateOutDir(outFile); err != nil {
return fmt.Errorf("error creating output directory for file %s: %w", outFile, err)
}

return os.WriteFile(outFile, envBytes, 0644) //nolint:gosec
}
16 changes: 14 additions & 2 deletions scai-gen/fileio/pb.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,24 @@ import (
"google.golang.org/protobuf/proto"
)

func WritePbToFile(pb proto.Message, outFile string) error {
pbBytes, err := protojson.Marshal(pb)
func WritePbToFile(pb proto.Message, outFile string, pretty bool) error {
opt := &protojson.MarshalOptions{}
if pretty {
opt.Multiline = true
opt.Indent = " "
opt.EmitUnpopulated = false
}

pbBytes, err := opt.Marshal(pb)
if err != nil {
return err
}

// ensure the out directory exists
if err = CreateOutDir(outFile); err != nil {
return fmt.Errorf("error creating output directory for file %s: %w", outFile, err)
}

return os.WriteFile(outFile, pbBytes, 0644) //nolint:gosec
}

Expand Down
Loading