Skip to content

Commit 4f96202

Browse files
committed
Support Git signatures
1 parent 773f614 commit 4f96202

21 files changed

+300
-91
lines changed

cmd/status.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,24 @@ var statusCmd = &cobra.Command{
5858
}
5959
fmt.Printf(" Need to reboot: %s\n", needToReboot)
6060
fmt.Printf(" Fetcher\n")
61+
if status.Fetcher.RepositoryStatus.SelectedCommitShouldBeSigned {
62+
if status.Fetcher.RepositoryStatus.SelectedCommitSigned {
63+
fmt.Printf(" Commit %s signed by %s\n", status.Fetcher.RepositoryStatus.SelectedCommitId, status.Fetcher.RepositoryStatus.SelectedCommitSignedBy)
64+
} else {
65+
fmt.Printf(" Commit %s is not signed while it should be\n", status.Fetcher.RepositoryStatus.SelectedCommitId)
66+
}
67+
}
6168
for _, r := range status.Fetcher.RepositoryStatus.Remotes {
6269
fmt.Printf(" Remote %s %s fetched %s\n",
6370
r.Name, r.Url, humanize.Time(r.FetchedAt),
6471
)
6572
}
6673
fmt.Printf(" Builder\n")
67-
builder.GenerationShow(*status.Builder.Generation)
74+
if status.Builder.Generation != nil {
75+
builder.GenerationShow(*status.Builder.Generation)
76+
} else {
77+
fmt.Printf(" No build available\n")
78+
}
6879
status.Deployer.Show(" ")
6980
},
7081
}

docs/generated-module-options.md

+18
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,24 @@ string
122122

123123

124124

125+
## services\.comin\.gpgPublicKeyPaths
126+
127+
128+
129+
A list of GPG public key file paths\. Each of this file should contains an armored GPG key\.
130+
131+
132+
133+
*Type:*
134+
list of Concatenated string
135+
136+
137+
138+
*Default:*
139+
` [ ] `
140+
141+
142+
125143
## services\.comin\.hostname
126144

127145

docs/howtos.md

+8
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,11 @@ the `/etc/machine-id` file), comin won't deploy the configuration.
6161
So, to migrate to another machine, you have to update this
6262
option in the `testing-<hostname>` branch in order to only deploy this
6363
configuration to the new machine.
64+
65+
## Check the Git commit signature
66+
67+
The option `services.comin.gpgPublicKeyPaths` allows to declare a list
68+
a GPG public keys. If `services.comin.gpgPublicKeyPaths != []`, comin **only** evaluates commits signed
69+
by one of these GPG public keys. Note only the last commit needs to be signed.
70+
71+
The file containing a GPG public key has to be created with `gpg --armor --export [email protected]`.

flake.nix

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
./main.go
4343
];
4444
};
45-
vendorHash = "sha256-VP8y/iSBIXZFfSmhHsXkp6RxP+2DovX3PbEDtMUMyYE=";
45+
vendorHash = "sha256-8RkxEDnPZJAWOo9uITELewc2UfoJ86DMGUi+Mi801/g=";
4646
ldflags = [
4747
"-X github.com/nlewo/comin/cmd.version=${version}"
4848
];

go.mod

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/nlewo/comin
33
go 1.22
44

55
require (
6+
github.com/ProtonMail/go-crypto v1.1.5
67
github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df
78
github.com/dustin/go-humanize v1.0.1
89
github.com/go-co-op/gocron/v2 v2.11.0
@@ -18,10 +19,9 @@ require (
1819
require (
1920
dario.cat/mergo v1.0.0 // indirect
2021
github.com/Microsoft/go-winio v0.6.1 // indirect
21-
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect
2222
github.com/beorn7/perks v1.0.1 // indirect
2323
github.com/cespare/xxhash/v2 v2.2.0 // indirect
24-
github.com/cloudflare/circl v1.3.6 // indirect
24+
github.com/cloudflare/circl v1.3.7 // indirect
2525
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
2626
github.com/davecgh/go-spew v1.1.1 // indirect
2727
github.com/emirpasic/gods v1.18.1 // indirect

go.sum

+4-43
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
33
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
44
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
55
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
6-
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE=
7-
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
6+
github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4=
7+
github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
88
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
99
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
1010
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
@@ -13,12 +13,10 @@ github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLo
1313
github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM=
1414
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
1515
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
16-
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
1716
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
1817
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
19-
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
20-
github.com/cloudflare/circl v1.3.6 h1:/xbKIqSHbZXHwkhbrhrt2YOHIwYJlXH94E3tI/gDlUg=
21-
github.com/cloudflare/circl v1.3.6/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
18+
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
19+
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
2220
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
2321
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
2422
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
@@ -104,74 +102,37 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
104102
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
105103
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
106104
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
107-
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
108105
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
109106
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
110-
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
111-
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
112107
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
113-
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
114-
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
115108
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
116109
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
117110
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
118111
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
119-
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
120-
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
121112
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
122113
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
123-
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
124-
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
125114
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
126-
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
127-
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
128-
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
129-
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
130115
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
131116
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
132-
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
133-
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
134-
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
135117
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
136118
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
137-
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
138119
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
139120
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
140121
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
141122
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
142123
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
143-
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
144124
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
145-
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
146-
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
147-
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
148-
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
149-
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
150125
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
151126
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
152127
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
153-
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
154-
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
155-
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
156-
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
157128
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
158129
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
159-
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
160-
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
161130
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
162-
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
163-
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
164-
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
165-
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
166131
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
167132
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
168133
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
169-
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
170-
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
171-
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
172134
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
173135
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
174-
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
175136
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
176137
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
177138
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

internal/config/config.go

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package config
22

33
import (
4-
"github.com/nlewo/comin/internal/types"
5-
"github.com/sirupsen/logrus"
6-
"gopkg.in/yaml.v2"
74
"os"
85
"path/filepath"
96
"strings"
7+
8+
"github.com/nlewo/comin/internal/types"
9+
"github.com/sirupsen/logrus"
10+
"gopkg.in/yaml.v2"
1011
)
1112

1213
func Read(path string) (config types.Configuration, err error) {
@@ -57,8 +58,9 @@ func Read(path string) (config types.Configuration, err error) {
5758

5859
func MkGitConfig(config types.Configuration) types.GitConfig {
5960
return types.GitConfig{
60-
Path: filepath.Join(config.StateDir, "repository"),
61-
Dir: config.FlakeSubdirectory,
62-
Remotes: config.Remotes,
61+
Path: filepath.Join(config.StateDir, "repository"),
62+
Dir: config.FlakeSubdirectory,
63+
Remotes: config.Remotes,
64+
GpgPublicKeyPaths: config.GpgPublicKeyPaths,
6365
}
6466
}

internal/manager/manager.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,12 @@ func (m *Manager) FetchAndBuild() {
7777
for {
7878
select {
7979
case rs := <-m.Fetcher.RepositoryStatusCh:
80-
logrus.Infof("manager: a generation is evaluating for commit %s", rs.SelectedCommitId)
81-
m.builder.Eval(rs)
80+
if !rs.SelectedCommitShouldBeSigned || rs.SelectedCommitSigned {
81+
logrus.Infof("manager: a generation is evaluating for commit %s", rs.SelectedCommitId)
82+
m.builder.Eval(rs)
83+
} else {
84+
logrus.Infof("manager: the commit %s is not evaluated because it is not signed", rs.SelectedCommitId)
85+
}
8286
case generation := <-m.builder.EvaluationDone:
8387
if generation.EvalErr != nil {
8488
continue

internal/repository/fail.public

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-----BEGIN PGP PUBLIC KEY BLOCK-----
2+
3+
mDMEZ4oDaRYJKwYBBAHaRw8BAQdA91zbRSdMphKMs7wP+3/mOpDkxEfeWrfblS5t
4+
uf5xw1O0F2ZhaWwgPGZhaWxAY29taW4uc3BhY2U+iJQEExYKADwWIQSNo3AzK05c
5+
jADI4rwfTCYbHTKLkgUCZ4oDaQIbAwUJBaOagAQLCQgHBBUKCQgFFgIDAQACHgUC
6+
F4AACgkQH0wmGx0yi5IEyAD/ck8A4aPUK8+g7EzMLRnl+twUccwmS7wIthLsA7Sm
7+
s0sA/2RMyImXOK82hesQi8VqV/XNsu/n5Lg6bAfkTHQR1CwLuDgEZ4oDaRIKKwYB
8+
BAGXVQEFAQEHQLr2P/jpdMyluCmFv1mmtHxNy4rOAstT61B+Zsq+8/wtAwEIB4h+
9+
BBgWCgAmFiEEjaNwMytOXIwAyOK8H0wmGx0yi5IFAmeKA2kCGwwFCQWjmoAACgkQ
10+
H0wmGx0yi5IXxwD6AwMQTzw4uXuMJiNC3lsaX5+L9vJDy4tSu/bufc4EKPoA/iiu
11+
kbksGGr4c6gTHOovFhEklvJhjPcEcwdvdEnioWgL
12+
=zjq4
13+
-----END PGP PUBLIC KEY BLOCK-----

internal/repository/git.go

+9-19
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ package repository
33
import (
44
"context"
55
"fmt"
6-
"io/ioutil"
76
"time"
87

8+
"github.com/ProtonMail/go-crypto/openpgp"
99
"github.com/go-git/go-git/v5"
1010
gitConfig "github.com/go-git/go-git/v5/config"
1111
"github.com/go-git/go-git/v5/plumbing"
@@ -222,31 +222,21 @@ func manageRemote(r *git.Repository, remote types.Remote) error {
222222
return nil
223223
}
224224

225-
func verifyHead(r *git.Repository, config types.GitConfig) error {
225+
func headSignedBy(r *git.Repository, publicKeys []string) (signedBy *openpgp.Entity, err error) {
226226
head, err := r.Head()
227227
if head == nil {
228-
return fmt.Errorf("Repository HEAD should not be nil")
228+
return nil, fmt.Errorf("Repository HEAD should not be nil")
229229
}
230-
logrus.Debugf("Repository HEAD is %s", head.Strings()[1])
231-
232230
commit, err := r.CommitObject(head.Hash())
233231
if err != nil {
234-
return err
232+
return nil, err
235233
}
236-
237-
for _, keyPath := range config.GpgPublicKeyPaths {
238-
key, err := ioutil.ReadFile(keyPath)
239-
if err != nil {
240-
return err
241-
}
242-
entity, err := commit.Verify(string(key))
243-
if err != nil {
244-
logrus.Debug(err)
245-
} else {
234+
for _, k := range publicKeys {
235+
entity, err := commit.Verify(k)
236+
if err == nil {
246237
logrus.Debugf("Commit %s signed by %s", head.Hash(), entity.PrimaryIdentity().Name)
247-
return nil
238+
return entity, nil
248239
}
249-
250240
}
251-
return fmt.Errorf("Commit %s is not signed", head.Hash())
241+
return nil, fmt.Errorf("Commit %s is not signed", head.Hash())
252242
}

internal/repository/git_test.go

+37-5
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
package repository
22

33
import (
4+
"os"
5+
"path/filepath"
6+
"testing"
7+
"time"
8+
9+
"github.com/ProtonMail/go-crypto/openpgp"
410
"github.com/go-git/go-git/v5"
511
"github.com/go-git/go-git/v5/plumbing"
612
"github.com/go-git/go-git/v5/plumbing/object"
713
"github.com/stretchr/testify/assert"
8-
"io/ioutil"
9-
"path/filepath"
10-
"testing"
11-
"time"
1214
)
1315

1416
func commitFile(remoteRepository *git.Repository, dir, branch, content string) (commitId string, err error) {
17+
return commitFileAndSign(remoteRepository, dir, branch, content, nil)
18+
}
19+
20+
func commitFileAndSign(remoteRepository *git.Repository, dir, branch, content string, signKey *openpgp.Entity) (commitId string, err error) {
1521
w, err := remoteRepository.Worktree()
1622
if err != nil {
1723
return
@@ -22,7 +28,7 @@ func commitFile(remoteRepository *git.Repository, dir, branch, content string) (
2228
})
2329

2430
filename := filepath.Join(dir, content)
25-
err = ioutil.WriteFile(filename, []byte(content), 0644)
31+
err = os.WriteFile(filename, []byte(content), 0644)
2632
if err != nil {
2733
return
2834
}
@@ -36,6 +42,7 @@ func commitFile(remoteRepository *git.Repository, dir, branch, content string) (
3642
3743
When: time.Unix(0, 0),
3844
},
45+
SignKey: signKey,
3946
})
4047
if err != nil {
4148
return
@@ -119,3 +126,28 @@ func TestIsAncestor(t *testing.T) {
119126

120127
//time.Sleep(100*time.Second)
121128
}
129+
130+
func TestHeadSignedBy(t *testing.T) {
131+
dir := t.TempDir()
132+
remoteRepository, _ := git.PlainInit(dir, false)
133+
134+
r, err := os.Open("./test.private")
135+
entityList, _ := openpgp.ReadArmoredKeyRing(r)
136+
commitFileAndSign(remoteRepository, dir, "main", "file-1", entityList[0])
137+
138+
failPublic, _ := os.ReadFile("./fail.public")
139+
testPublic, _ := os.ReadFile("./test.public")
140+
signedBy, err := headSignedBy(remoteRepository, []string{string(failPublic), string(testPublic)})
141+
assert.Nil(t, err)
142+
assert.Equal(t, "test <[email protected]>", signedBy.PrimaryIdentity().Name)
143+
144+
signedBy, err = headSignedBy(remoteRepository, []string{string(failPublic)})
145+
assert.ErrorContains(t, err, "is not signed")
146+
assert.Nil(t, signedBy)
147+
148+
commitFileAndSign(remoteRepository, dir, "main", "file-2", nil)
149+
signedBy, err = headSignedBy(remoteRepository, []string{string(failPublic), string(testPublic)})
150+
assert.ErrorContains(t, err, "is not signed")
151+
assert.Nil(t, signedBy)
152+
153+
}

internal/repository/invalid.public

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Not a valid armored GPG pub key

0 commit comments

Comments
 (0)