-
Notifications
You must be signed in to change notification settings - Fork 16
/
cmd_init.py
executable file
·209 lines (158 loc) · 6.56 KB
/
cmd_init.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#!/usr/bin/python2
#
# Copyright (c) 2010-2013 Liraz Siri <[email protected]>
#
# This file is part of TKLBAM (TurnKey GNU/Linux BAckup and Migration).
#
# TKLBAM is open source software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3 of
# the License, or (at your option) any later version.
#
"""
Initialization (start here)
By default, this links TKLBAM to your Hub account and downloads an appropriate
backup profile, which is used to calculate the list of system changes we need
to backup. On a TurnKey system the profile describes the installation state of
the appliance and contains a list of packages, filesystem paths to scan for
changes and an index of the contents of those paths which records timestamps,
ownership and permissions. On a non-TurnKey system the default backup profile
will not describe installation state, only a list of directories to backup.
Arguments:
API-KEY Cut and paste this from your Hub account's user profile.
Options:
--force Force re-initialization with new API-KEY.
--force-profile=PROFILE_ID Force a specific backup profile
(e.g., "core", "turnkey-core-13.0-wheezy-amd64")
Without --force-profile the profile_id is
automatically detected.
--force-profile=empty "empty" is a special profile_id value that creates an empty
backup profile. Backup configurations will only be taken
from /etc/tklbam.
--force-profile=PATH Path to a custom backup profile
Details: tklbam-internal create-profile --help
--solo Solo mode: disables link to Hub.
You'll need to --force-profile=empty or use a custom profile
tklbam-backup will only work with --address or --dump options
tklbam-restore will only work with --address or a backup extract
Security warning:
Providing your Hub account's APIKEY as a command line argument is
potentially less secure than allowing tklbam-init to prompt you for it
interactively:
* The shell may save the APIKEY to its history file (e.g., ~/.bash_history)
* The APIKEY may briefly show up in the process list
Examples:
# initialize TKLBAM
tklbam-init
# initialize TKLBAM with the core profile
tklbam-init --force-profile=core
# initialize TKLBAM with a non-default registry path
TKLBAM_REGISTRY=/var/lib/tklbam2 tklbam-init
# initialize TKLBAM in solo mode with an empty profile
tklbam-init --solo --force-profile=empty
"""
import sys
import hub
import keypacket
import registry
from conf import Conf
import os
import base64
import struct
import hashlib
import getopt
def is_valid_apikey(apikey):
padded = "A" * (20 - len(apikey)) + apikey
try:
struct.unpack("!L8s", base64.b32decode(padded + "=" * 4))
except TypeError:
return False
return True
def generate_secret():
# effective is key size: 160-bits (SHA1)
# base64 encoding to ensure cli safeness
# urandom guarantees we won't block. Redundant randomness just in case.
return base64.b64encode(hashlib.sha1(os.urandom(32)).digest()).rstrip("=")
def fatal(e):
print >> sys.stderr, "error: " + str(e)
sys.exit(1)
def usage(e=None):
from paged import stdout
if e:
print >> stdout, "error: " + str(e)
print >> stdout, "Usage: %s [ API-KEY ]" % sys.argv[0]
print >> stdout, __doc__.strip()
sys.exit(1)
def main():
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], "h", ["help", "solo", "force", "force-profile="])
except getopt.GetoptError, e:
usage(e)
apikey = None
force = False
force_profile = False
solo = False
conf = Conf()
for opt, val in opts:
if opt in ('-h', '--help'):
usage()
elif opt == '--force':
force = True
elif opt == '--force-profile':
force_profile = True
conf.force_profile = val
elif opt == "--solo":
solo = True
if args:
if len(args) != 1:
usage()
apikey = args[0]
if not registry.registry.secret:
registry.registry.secret = generate_secret()
registry.registry.key = keypacket.fmt(registry.registry.secret, "")
print """\
Generated backup encryption key:
For extra security run "tklbam-passphrase" to cryptographically protect it
with a passphrase, which will be needed later to restore. If you use lose
the passphrase it will be impossible to restore your backup and you may
suffer data loss. To safeguard against this you may want to create an
escrow key with "tklbam-escrow".
"""
if solo:
if registry.registry.sub_apikey:
print "Broken TKLBAM link to your Hub account (--solo mode)"
registry.registry.sub_apikey = None
registry.registry.credentials = None
else:
if force or not registry.registry.sub_apikey:
if not apikey:
print "Copy paste the API-KEY from your Hub account's user profile"
print
while True:
apikey = raw_input("API-KEY: ").strip()
if apikey:
break
if not is_valid_apikey(apikey):
fatal("'%s' is an invalid API-KEY" % apikey)
try:
sub_apikey = hub.Backups.get_sub_apikey(apikey)
except Exception, e:
fatal(e)
registry.registry.sub_apikey = sub_apikey
hb = hub.Backups(sub_apikey)
try:
credentials = hb.get_credentials()
registry.registry.credentials = credentials
print "Linked TKLBAM to your Hub account."
except hub.NotSubscribed, e:
print "Linked TKLBAM to your Hub account but there's a problem:"
print
elif not force_profile and registry.registry.profile:
fatal("already initialized")
if force_profile or not registry.registry.profile:
try:
registry.update_profile(conf.force_profile)
except hub.Backups.NotInitialized:
fatal("--solo requires --force-profile=empty or --force-profile=path/to/custom/profile ")
if __name__=="__main__":
main()