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
1 change: 1 addition & 0 deletions .github/workflows/local_attest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: SLSA Source
on:
push:
branches: [ "main" ]
tags: ['**']

jobs:
# Whenever new source is pushed recompute the slsa source information.
Expand Down
8 changes: 7 additions & 1 deletion DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ This tool can also check to see if the GitHub repo/ref is configured to require
### IMMUTABLE_TAGS

This tool can also check to see if the GitHub repo is configured to require
immutable tags. To do so it checks that the repo:
immutable tags. To do so it checks that the repo enables the follow rules
to ~ALL tags:

1. Doesn't allow tag updates
2. Doesn't allow tag deletions
Expand All @@ -243,6 +244,11 @@ Importing [rulesets/tag_immutability.json](rulesets/tag_immutability.json)
to a repos rulesets will enable the repo controls. The `immutable_tags`
field in the policy then needs to be enabled too.

TODO: In the future this tool could be updated to allow some subset of tags
to be updated (e.g. `latest`, `nightly`), but that feature is not yet
supported. Tracked
[here](https://github.com/slsa-framework/slsa-source-poc/issues/129).

## Open Issues

### Dealing with reliability
Expand Down
11 changes: 9 additions & 2 deletions actions/slsa_with_provenance/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,18 @@ runs:
- id: setup
run: mkdir -p metadata
shell: bash
- id: determine_level
- id: handle_branch_push
if: ${{ startsWith(github.ref, 'refs/heads/') }}
run: |
echo "## SLSA Source Properties" >> $GITHUB_STEP_SUMMARY
echo "## SLSA Source Properties Branch Push" >> $GITHUB_STEP_SUMMARY
go run github.com/slsa-framework/slsa-source-poc/sourcetool@8de659f119d933d4cfaed300e7d8bd78528a48c7 --github_token ${{ github.token }} checklevelprov --commit ${{ github.sha }} --owner ${{ github.repository_owner }} --repo ${{ github.event.repository.name }} --branch ${{ github.ref_name }} --output_signed_bundle ${{ github.workspace }}/metadata/signed_bundle.intoto.jsonl >> $GITHUB_STEP_SUMMARY
shell: bash
- id: handle_tag_push
if: ${{ startsWith(github.ref, 'refs/tags/') }}
run: |
echo "## SLSA Source Properties Tag Push" >> $GITHUB_STEP_SUMMARY
echo "TODO"
shell: bash
- id: summary
run: |
echo "## Signed Bundle" >> $GITHUB_STEP_SUMMARY
Expand Down
2 changes: 1 addition & 1 deletion go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
github.com/bufbuild/protocompile v0.10.0/go.mod h1:G9qQIQo0xZ6Uyj6CMNz0saGmx2so+KONo8/KrELABiY=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/buildkite/agent/v3 v3.81.0/go.mod h1:edJeyycODRxaFvpT22rDGwaQ5oa4eB8GjtbjgX5VpFw=
github.com/buildkite/go-pipeline v0.13.1/go.mod h1:2HHqlSFTYgHFhzedJu0LhLs9n5c9XkYnHiQFVN5HE4U=
github.com/buildkite/interpolate v0.1.3/go.mod h1:UNVe6A+UfiBNKbhAySrBbZFZFxQ+DXr9nWen6WVt/A8=
Expand Down Expand Up @@ -180,7 +181,6 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3
github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA=
github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
Expand Down
9 changes: 6 additions & 3 deletions policy/github.com/TomHennen/Concordance/source-policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
"Name": "master",
"Since": "2025-03-23T18:08:43.25099739Z",
"target_slsa_source_level": "SLSA_SOURCE_LEVEL_3",
"require_review": false,
"immutable_tags": true
"require_review": false
}
]
],
"protected_tag": {
"Since": "2025-03-23T18:08:43.25099739Z",
"immutable_tags": true
}
}
12 changes: 6 additions & 6 deletions sourcetool/cmd/checklevel.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,22 @@ func doCheckLevel(commit, owner, repo, branch, outputVsa, outputUnsignedVsa stri
log.Fatal("Must set commit, owner, repo, and branch flags.")
}

gh_connection := gh_control.NewGhConnection(owner, repo, branch).WithAuthToken(githubToken)
gh_connection := gh_control.NewGhConnection(owner, repo, gh_control.BranchToFullRef(branch)).WithAuthToken(githubToken)
ctx := context.Background()

controlStatus, err := gh_connection.GetControls(ctx, commit)
controlStatus, err := gh_connection.GetBranchControls(ctx, commit, gh_connection.GetFullRef())
if err != nil {
log.Fatal(err)
}
pol := policy.NewPolicy()
pol.UseLocalPolicy = checkLevelProvArgs.useLocalPolicy
verifiedLevels, policyPath, err := pol.EvaluateControl(ctx, gh_connection, controlStatus)
pe := policy.NewPolicyEvaluator()
pe.UseLocalPolicy = checkLevelProvArgs.useLocalPolicy
verifiedLevels, policyPath, err := pe.EvaluateControl(ctx, gh_connection, controlStatus)
if err != nil {
log.Fatal(err)
}
fmt.Print(verifiedLevels)

unsignedVsa, err := attest.CreateUnsignedSourceVsa(gh_connection, commit, verifiedLevels, policyPath)
unsignedVsa, err := attest.CreateUnsignedSourceVsa(gh_connection.GetRepoUri(), gh_connection.GetFullRef(), commit, verifiedLevels, policyPath)
if err != nil {
log.Fatal(err)
}
Expand Down
14 changes: 7 additions & 7 deletions sourcetool/cmd/checklevelprov.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var (

func doCheckLevelProv(checkLevelProvArgs CheckLevelProvArgs) {
gh_connection :=
gh_control.NewGhConnection(checkLevelProvArgs.owner, checkLevelProvArgs.repo, checkLevelProvArgs.branch).WithAuthToken(githubToken)
gh_control.NewGhConnection(checkLevelProvArgs.owner, checkLevelProvArgs.repo, gh_control.BranchToFullRef(checkLevelProvArgs.branch)).WithAuthToken(githubToken)
ctx := context.Background()

prevCommit := checkLevelProvArgs.prevCommit
Expand All @@ -58,22 +58,22 @@ func doCheckLevelProv(checkLevelProvArgs CheckLevelProvArgs) {
}
}

pa := attest.NewProvenanceAttestor(gh_connection, getVerificationOptions())
prov, err := pa.CreateSourceProvenance(ctx, checkLevelProvArgs.prevBundlePath, checkLevelProvArgs.commit, prevCommit)
pa := attest.NewProvenanceAttestor(gh_connection, getVerifier())
prov, err := pa.CreateSourceProvenance(ctx, checkLevelProvArgs.prevBundlePath, checkLevelProvArgs.commit, prevCommit, gh_connection.GetFullRef())
if err != nil {
log.Fatal(err)
}

// check p against policy
pol := policy.NewPolicy()
pol.UseLocalPolicy = checkLevelProvArgs.useLocalPolicy
verifiedLevels, policyPath, err := pol.EvaluateProv(ctx, gh_connection, prov)
pe := policy.NewPolicyEvaluator()
pe.UseLocalPolicy = checkLevelProvArgs.useLocalPolicy
verifiedLevels, policyPath, err := pe.EvaluateSourceProv(ctx, gh_connection, prov)
if err != nil {
log.Fatal(err)
}

// create vsa
unsignedVsa, err := attest.CreateUnsignedSourceVsa(gh_connection, checkLevelProvArgs.commit, verifiedLevels, policyPath)
unsignedVsa, err := attest.CreateUnsignedSourceVsa(gh_connection.GetRepoUri(), gh_connection.GetFullRef(), checkLevelProvArgs.commit, verifiedLevels, policyPath)
if err != nil {
log.Fatal(err)
}
Expand Down
108 changes: 108 additions & 0 deletions sourcetool/cmd/checktag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
Copyright © 2025 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
"context"
"log"
"os"

"github.com/slsa-framework/slsa-source-poc/sourcetool/pkg/attest"
"github.com/slsa-framework/slsa-source-poc/sourcetool/pkg/gh_control"
"github.com/slsa-framework/slsa-source-poc/sourcetool/pkg/policy"
"github.com/spf13/cobra"
"google.golang.org/protobuf/encoding/protojson"
)

type CheckTagArgs struct {
commit string
owner string
repo string
tagName string
outputSignedBundle string
useLocalPolicy string
}

var (
checkTagArgs CheckTagArgs
// checktagCmd represents the checktag command
checktagCmd = &cobra.Command{
Use: "checktag",
Short: "Checks to see if the tag operation should be allowed and issues a VSA",
Run: func(cmd *cobra.Command, args []string) {
doCheckTag(checkTagArgs)
},
}
)

func doCheckTag(args CheckTagArgs) {
gh_connection :=
gh_control.NewGhConnection(args.owner, args.repo, gh_control.TagToFullRef(args.tagName)).WithAuthToken(githubToken)
ctx := context.Background()
verifier := getVerifier()

// Create tag provenance.
pa := attest.NewProvenanceAttestor(gh_connection, verifier)
prov, err := pa.CreateTagProvenance(ctx, args.commit, gh_control.TagToFullRef(args.tagName))
if err != nil {
log.Fatal(err)
}

// check p against policy
pe := policy.NewPolicyEvaluator()
pe.UseLocalPolicy = args.useLocalPolicy
verifiedLevels, policyPath, err := pe.EvaluateTagProv(ctx, gh_connection, prov)
if err != nil {
log.Fatal(err)
}

// create vsa
unsignedVsa, err := attest.CreateUnsignedSourceVsa(gh_connection.GetRepoUri(), gh_connection.GetFullRef(), args.commit, verifiedLevels, policyPath)
if err != nil {
log.Fatal(err)
}

unsignedProv, err := protojson.Marshal(prov)
if err != nil {
log.Fatal(err)
}

if args.outputSignedBundle != "" {
f, err := os.OpenFile(args.outputSignedBundle, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
log.Fatal(err)
}
defer f.Close()

signedProv, err := attest.Sign(string(unsignedProv))
if err != nil {
log.Fatal(err)
}

signedVsa, err := attest.Sign(unsignedVsa)
if err != nil {
log.Fatal(err)
}

f.WriteString(signedProv)
f.WriteString("\n")
f.WriteString(signedVsa)
f.WriteString("\n")
} else {
log.Printf("unsigned prov: %s\n", unsignedProv)
log.Printf("unsigned vsa: %s\n", unsignedVsa)
}
}

func init() {
rootCmd.AddCommand(checktagCmd)

checktagCmd.Flags().StringVar(&checkTagArgs.commit, "commit", "", "The commit to check - required.")
checktagCmd.Flags().StringVar(&checkTagArgs.owner, "owner", "", "The GitHub repository owner - required.")
checktagCmd.Flags().StringVar(&checkTagArgs.repo, "repo", "", "The GitHub repository name - required.")
checktagCmd.Flags().StringVar(&checkTagArgs.tagName, "tag_name", "", "The name of the new tag - required.")
checktagCmd.Flags().StringVar(&checkTagArgs.outputSignedBundle, "output_signed_bundle", "", "The path to write a bundle of signed attestations.")
checktagCmd.Flags().StringVar(&checkTagArgs.useLocalPolicy, "use_local_policy", "", "UNSAFE: Use the policy at this local path instead of the official one.")

}
2 changes: 1 addition & 1 deletion sourcetool/cmd/createpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ var (
)

func doCreatePolicy(policyRepoPath, owner, repo, branch string) {
gh_connection := gh_control.NewGhConnection(owner, repo, branch).WithAuthToken(githubToken)
gh_connection := gh_control.NewGhConnection(owner, repo, gh_control.BranchToFullRef(branch)).WithAuthToken(githubToken)
ctx := context.Background()
outpath, err := policy.CreateLocalPolicy(ctx, gh_connection, policyRepoPath)
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions sourcetool/cmd/prov.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ var (
)

func doProv(prevAttPath, commit, prevCommit, owner, repo, branch string) {
gh_connection := gh_control.NewGhConnection(owner, repo, branch).WithAuthToken(githubToken)
gh_connection := gh_control.NewGhConnection(owner, repo, gh_control.BranchToFullRef(branch)).WithAuthToken(githubToken)
ctx := context.Background()
pa := attest.NewProvenanceAttestor(gh_connection, attest.DefaultVerifierOptions)
newProv, err := pa.CreateSourceProvenance(ctx, prevAttPath, commit, prevCommit)
pa := attest.NewProvenanceAttestor(gh_connection, getVerifier())
newProv, err := pa.CreateSourceProvenance(ctx, prevAttPath, commit, prevCommit, gh_connection.GetFullRef())
if err != nil {
log.Fatal(err)
}
Expand Down
4 changes: 2 additions & 2 deletions sourcetool/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ to quickly create a Cobra application.`,
}
)

func getVerificationOptions() attest.VerificationOptions {
func getVerifier() attest.Verifier {
options := attest.DefaultVerifierOptions
if checkLevelProvArgs.expectedIssuer != "" {
options.ExpectedIssuer = checkLevelProvArgs.expectedIssuer
}
if checkLevelProvArgs.expectedSan != "" {
options.ExpectedSan = checkLevelProvArgs.expectedSan
}
return options
return attest.NewBndVerifier(options)
}

// Execute adds all child commands to the root command and sets flags appropriately.
Expand Down
6 changes: 2 additions & 4 deletions sourcetool/cmd/verifycommit.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,10 @@ func doVerifyCommit(commit, owner, repo, branch string) {
log.Fatal("Must set commit, owner, repo, and branch flags.")
}

gh_connection := gh_control.NewGhConnection(owner, repo, branch).WithAuthToken(githubToken)
gh_connection := gh_control.NewGhConnection(owner, repo, gh_control.BranchToFullRef(branch)).WithAuthToken(githubToken)
ctx := context.Background()

pa := attest.NewProvenanceAttestor(gh_connection, getVerificationOptions())

_, vsaPred, err := pa.GetVsa(ctx, commit)
_, vsaPred, err := attest.GetVsa(ctx, gh_connection, getVerifier(), commit, gh_connection.GetFullRef())
if err != nil {
log.Fatal(err)
}
Expand Down
4 changes: 4 additions & 0 deletions sourcetool/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/go-git/go-git/v5 v5.13.2
github.com/google/go-github/v69 v69.2.0
github.com/in-toto/attestation v1.1.1
github.com/migueleliasweb/go-github-mock v1.3.0
github.com/sigstore/sigstore-go v0.7.0
github.com/spf13/cobra v1.9.1
google.golang.org/protobuf v1.36.5
Expand Down Expand Up @@ -47,8 +48,10 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/certificate-transparency-go v1.3.1 // indirect
github.com/google/go-containerregistry v0.20.3 // indirect
github.com/google/go-github/v71 v71.0.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
Expand Down Expand Up @@ -109,6 +112,7 @@ require (
golang.org/x/sys v0.30.0 // indirect
golang.org/x/term v0.29.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.9.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
Expand Down
10 changes: 8 additions & 2 deletions sourcetool/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,14 @@ github.com/google/certificate-transparency-go v1.3.1 h1:akbcTfQg0iZlANZLn0L9xOeW
github.com/google/certificate-transparency-go v1.3.1/go.mod h1:gg+UQlx6caKEDQ9EElFOujyxEQEfOiQzAt6782Bvi8k=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI=
github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI=
github.com/google/go-github/v69 v69.2.0 h1:wR+Wi/fN2zdUx9YxSmYE0ktiX9IAR/BeePzeaUUbEHE=
github.com/google/go-github/v69 v69.2.0/go.mod h1:xne4jymxLR6Uj9b7J7PyTpkMYstEMMwGZa0Aehh1azM=
github.com/google/go-github/v71 v71.0.0 h1:Zi16OymGKZZMm8ZliffVVJ/Q9YZreDKONCr+WUd0Z30=
github.com/google/go-github/v71 v71.0.0/go.mod h1:URZXObp2BLlMjwu0O8g4y6VBneUj2bCHgnI8FfgZ51M=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
Expand All @@ -199,6 +201,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gT
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
Expand Down Expand Up @@ -275,6 +279,8 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/migueleliasweb/go-github-mock v1.3.0 h1:2sVP9JEMB2ubQw1IKto3/fzF51oFC6eVWOOFDgQoq88=
github.com/migueleliasweb/go-github-mock v1.3.0/go.mod h1:ipQhV8fTcj/G6m7BKzin08GaJ/3B5/SonRAkgrk0zCY=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
Expand Down
Loading
Loading