1
1
import os
2
+ import pprint
2
3
import random
3
4
5
+ import gnupg
4
6
from git import Actor , Repo
5
7
6
8
7
- def main ():
8
-
9
+ def create_temp_dir ():
9
10
# Create temp dir
10
11
dir_name = random .getrandbits (128 )
11
12
temp_dir = f'/tmp/{ dir_name } '
12
13
print (f'Creating temp dir: { temp_dir } ' )
13
14
os .mkdir (temp_dir )
15
+ return temp_dir
16
+
14
17
18
+ def git_init (temp_dir ):
15
19
print ('Initializing repo ...' )
16
20
repo = Repo .init (temp_dir )
21
+ return repo
22
+
23
+
24
+ def execute_console_command (command ):
25
+ print (f'Executing command: { command } ' )
26
+ output = os .popen (command ).read ()
27
+ print (output )
17
28
18
- #
19
- # Commit without signature
20
- #
21
29
30
+ def print_git_config_option (option ):
31
+ command = f'git config --get { option } '
32
+ print (f'Executing command: { command } ' )
33
+ output = os .popen (command ).read ()
34
+ print (output )
35
+
36
+
37
+ def commit_without_signning (temp_dir , repo ):
22
38
# Create file
23
39
filename = "README.md"
24
40
file_path = temp_dir + '/' + filename
@@ -41,10 +57,8 @@ def main():
41
57
output = os .popen (command ).read ()
42
58
print (output )
43
59
44
- #
45
- # Commit with signature
46
- #
47
60
61
+ def signed_commit (temp_dir , repo , gpg_private_key , passphrase ):
48
62
# The GPG key:
49
63
# sec rsa4096/27304EDD6079B81C 2021-11-19 [SC]
50
64
# 88966A5B8C01BD04F3DA440427304EDD6079B81C
@@ -62,30 +76,118 @@ def main():
62
76
index = repo .index
63
77
index .add ([file_path ])
64
78
65
- # List keys: gpg --list-secret-keys --keyid-format=long
66
- # Show public key: gpg --armor --export 5B6BDD35BEDFBF6F
67
-
68
- # Commit with signature
79
+ # gpg commands:
80
+ # List keys: gpg --list-secret-keys --keyid-format=long
81
+ # Show public key: gpg --armor --export 27304EDD6079B81C
82
+ # Export private key: gpg --output private_key.pgp --armor --export-secret-key 27304EDD6079B81C
83
+ # Export private key:
84
+ # (for env var) gpg -a --export-secret-keys 88966A5B8C01BD04F3DA440427304EDD6079B81C | cat -e | sed 's/\$/\\n/g'
85
+ # Import pgp key: echo -e $GPG_PRIVATE_KEY | gpg --import
86
+ # Get keygrips: gpg --batch --with-colons --with-keygrip --list-secret-keys
87
+ # gpg --with-keygrip --list-secret-keys
88
+
89
+ # Needed for commit with signature:
90
+ # https://github.com/gitpython-developers/GitPython/issues/580#issuecomment-282474086
69
91
index .write ()
70
92
71
- signingkey = '5B6BDD35BEDFBF6F'
93
+ # TODO: get from console, gnupg package or env var
94
+ signingkey = '27304EDD6079B81C'
95
+ keygrip = '97D36F5B8F5BECDA8A1923FC00D11C7C438584F9'
96
+ fingerprint = '88966A5B8C01BD04F3DA440427304EDD6079B81C'
97
+ hex_passphrase = passphrase .encode ('utf-8' ).hex ().upper ()
98
+
99
+ # git config --global user.name "A committer"
72
100
repo .config_writer ().set_value ("user" , "name" , "A committer" ).release ()
101
+ # git config --global user.email "committer@example.com"
73
102
repo .config_writer ().set_value ("user" , "email" , "committer@example.com" ).release ()
74
103
repo .config_writer ().set_value ("user" , "signingkey" , signingkey ).release ()
75
104
repo .config_writer ().set_value ("commit" , "gpgsign" , "true" ).release ()
76
105
77
- # TODO: set up private key from env varaible like "crazy-max/ghaction-import-gpg" action
78
-
79
- repo .git .commit ('-S' , f'--gpg-sign={ signingkey } ' , '-m' , 'my commit message 2' ,
80
- author = 'A committer <committer@example.com>' )
106
+ # Debug: git Python package does not write global options on the root git config file
107
+ # print_git_config_option('user.name')
108
+ # print_git_config_option('user.email')
109
+ # print_git_config_option('user.signingkey')
110
+ # print_git_config_option('commit.gpgsign')
111
+
112
+ gpg = gnupg .GPG (gnupghome = '/root/.gnupg' , verbose = True , use_agent = True )
113
+
114
+ # Import private key
115
+ result = gpg .import_keys (gpg_private_key , passphrase = passphrase )
116
+ # print(gpg_private_key, passphrase)
117
+ pprint .pprint (result )
118
+
119
+ # Print gpg keys using Python package
120
+ # keys = gpg.list_keys()
121
+ # pprint.pprint(keys)
122
+ keys = gpg .list_keys (True )
123
+ # pprint.pprint(keys)
124
+
125
+ # Print gpg keys using console command
126
+ execute_console_command ('gpg --list-secret-keys --keyid-format=long' )
127
+ # Print GPG agent conf
128
+ execute_console_command ('cat /root/.gnupg/gpg-agent.conf' )
129
+ # Print global git config. With docker we use root user and it does not have a .gitconfig file
130
+ execute_console_command ('cat ~/.gitconfig' )
131
+
132
+ # Reload PGP agent
133
+ # reload_pgp_agent_command = 'gpg-connect-agent reloadagent /bye'
134
+ # execute_console_command(reload_pgp_agent_command)
135
+ #execute_console_command('gpg-agent --daemon --allow-preset-passphrase')
136
+
137
+ #reload_agent_command = f'gpg-connect-agent \'RELOADAGENT\' /bye'
138
+ # execute_console_command(reload_agent_command)
139
+
140
+ gpg_agente_config = 'gpg-agent --gpgconf-list'
141
+ execute_console_command (gpg_agente_config )
142
+
143
+ # Preset passphrase using gpg-preset-passphrase:
144
+ # https://www.gnupg.org/documentation/manuals/gnupg/Invoking-gpg_002dpreset_002dpassphrase.html#Invoking-gpg_002dpreset_002dpassphrase
145
+ # This command makes git not prompt for passphrase for GPG key. We preset the PGP agent with the passphrase
146
+ # preset_passphrase_command = f'echo \'{passphrase}\' | /usr/lib/gnupg2/gpg-preset-passphrase -v --preset {keygrip}'
147
+ # execute_console_command(preset_passphrase_command)
148
+
149
+ # Preset passphrase using gpg-connect-agent:
150
+ # https://www.gnupg.org/documentation/manuals/gnupg/Agent-PRESET_005fPASSPHRASE.html#Agent-PRESET_005fPASSPHRASE
151
+ # https://github.com/crazy-max/ghaction-import-gpg/blob/60f6f3e9a98263cc2c51ebe1f9babe82ded3f0ba/src/gpg.ts#L170-L174
152
+ preset_passphrase_command = f'gpg-connect-agent \' PRESET_PASSPHRASE { keygrip } -1 { hex_passphrase } \' /bye'
153
+ execute_console_command (preset_passphrase_command )
154
+
155
+ # If we want ot ask the user for the passphrase (popup)
156
+ # https://www.gnupg.org/documentation/manuals/gnupg/Agent-GET_005fPASSPHRASE.html#Agent-GET_005fPASSPHRASE
157
+ # error = 'error'
158
+ # prompt = 'prompt'
159
+ # desc = 'desc'
160
+ # get_passphrase_command = f'gpg-connect-agent \'GET_PASSPHRASE {keygrip} error prompt desc\' /bye'
161
+ # execute_console_command(get_passphrase_command)
162
+
163
+ show_key_info_command = f"gpg-connect-agent 'KEYINFO { keygrip } ' /bye"
164
+ execute_console_command (show_key_info_command )
165
+
166
+ repo .git .commit ('-S' , f'--gpg-sign={ signingkey } ' , '-m' , '"my commit message 2"' ,
167
+ author = '"A committer <committer@example.com>"' )
81
168
82
169
# Print commit info
83
- command = f'cd { temp_dir } && git log'
84
- print (f'Executing command: { command } ' )
85
- output = os .popen (command ).read ()
86
- print (output )
170
+ execute_console_command (f'cd { temp_dir } && git log --show-signature' )
171
+
172
+
173
+ def main (gpg_private_key , passphrase ):
174
+ temp_dir = create_temp_dir ()
175
+ repo = git_init (temp_dir )
176
+
177
+ print ("COMMIT WITHOUT SIGNATURE" )
178
+ print ("------------------------" )
179
+ commit_without_signning (temp_dir , repo )
180
+
181
+ print ("COMMIT WITH SIGNATURE" )
182
+ print ("---------------------" )
183
+ signed_commit (temp_dir , repo , gpg_private_key , passphrase )
87
184
88
185
89
186
if __name__ == "__main__" :
90
187
# https://gitpython.readthedocs.io/
91
- main ()
188
+
189
+ # Get environment variables
190
+ gpg_private_key = os .getenv ('GPG_PRIVATE_KEY' ).replace (r'\n' , '\n ' )
191
+ passphrase = os .environ .get ('PASSPHRASE' )
192
+
193
+ main (gpg_private_key , passphrase )
0 commit comments