add functions to sign and verify strings using a key
[sfa.git] / cmdline / editRecord.py
1 #! /usr/bin/env python
2 from __future__ import with_statement
3
4 # sfi -- slice-based facility interface
5
6 import sys
7 import os, os.path
8 import getopt
9 import tempfile
10 from geni.util.cert import Keypair, Certificate
11 from geni.util.credential import Credential
12 from geni.util.geniclient import GeniClient
13 from geni.util.record import GeniRecord
14 from geni.util.gid import GID
15 from geni.util.gid import create_uuid
16
17 pubkeyfile = None
18 infile = None
19 outfile = None
20 gidfile = None
21 email = None
22 ip = None
23 dns = None
24 hrn = None
25 type = None
26 dump = False
27 extractgid = None
28 researcher = []
29
30 long_opts = ["infile=", "outfile=", "email=", "ip=", "dns=", "gidfile=", "hrn=", "pubkeyfile=", "type=", "addresearcher=", "delresearcher=", "dump", "extractgid="]
31
32 def showhelp():
33    print "syntax: editRecord.py <options>"
34    print "    --help                ... show help"
35    print "    --infile <name>       ... read record from file"
36    print "    --outfile <name>      ... write record to file"
37    print "    --dump                ... dump record to stdout"
38    print "    --extractgid <fn>     ... extract GID to filename"
39    print "    --gidfile <fn>        ... load gid from file"
40    print "    --pubkeyfile <name>   ... key to use when creating gid"
41    print "    --hrn <name>          ... set hrn"
42    print "    --type <type>         ... set type (user|slice|sa|ma|...)"
43    print "    --email <addr>        ... user: set email address"
44    print "    --ip <addr>           ... node: set ip address"
45    print "    --dns <hostname>      ... node: set hostname"
46    print "    --addresearcher <hrn> ... slice: add researcher"
47    print "    --delresearcher <hrn> ... slice: delete researcher"
48
49 def load_publickey_string(fn):
50    f = file(fn,"r")
51    key_string = f.read()
52
53    # if the filename is a private key file, then extract the public key
54    if "PRIVATE KEY" in key_string:
55        outfn = tempfile.mktemp()
56        cmd = "openssl rsa -in " + fn + " -pubout -outform PEM -out " + outfn
57        os.system(cmd)
58        f = file(outfn, "r")
59        key_string = f.read()
60        os.remove(outfn)
61
62    return key_string
63
64 def process_options():
65    global infile, outfile
66    global email, ip, dns, gidfile, hrn, type
67    global researcher
68    global dump, extractgid
69    global pubkeyfile
70
71    (options, args) = getopt.getopt(sys.argv[1:], '', long_opts)
72    for opt in options:
73        name = opt[0]
74        val = opt[1]
75
76        if name == "--help":
77            showhelp()
78            sys.exit(0)
79        elif name == "--infile":
80            infile = val
81        elif name == "--outfile":
82            outfile = val
83        elif name == "--email":
84            email = val
85        elif name == "--ip":
86            ip = val
87        elif name == "--dns":
88            dns = val
89        elif name == "--gidfile":
90            gidfile = val
91        elif name == "--pubkeyfile":
92            pubkeyfile = val
93        elif name == "--hrn":
94            hrn = val
95        elif name == "--type":
96            type = val
97        elif name == "--dump":
98            dump = True
99        elif name == "--extractgid":
100            extractgid = val
101        elif name == "--addresearcher":
102            researcher.append(val)
103        elif name == "--delresearcher":
104            researcher.append("-" + val)
105
106 def errorcheck(record):
107    geni_info = record.get_geni_info()
108
109    if not record.type:
110        print "Warning: no type specified"
111    if not record.type in ["user", "sa", "ma", "slice", "node"]:
112        print "Warning: unknown record type"
113    if not record.name:
114        print "Warning: unknown record name"
115    if (not record.gid) and (not ("create_gid" in geni_info)):
116        print "Warning: unknown record gid"
117        print "   use --hrn and --pubkeyfile to cause a gid to be created"
118
119    if record.type == "user":
120        if geni_info.get("email", None) == None:
121            print "Warning: unknown email in user record"
122
123    if record.type == "node":
124        if geni_info.get("ip",None) == None:
125            print "Warning: unknown ip in node record"
126        if geni_info.get("dns",None) == None:
127            print "Warning: unknown dns in node record"
128
129 # updates is a list of items to add or remove. If an item starts with "-", then
130 # it will be removed. Otherwise it will be added
131 def update_list(dict, listname, updates):
132    list = dict.get(listname, [])
133    for hrn in updates:
134        if hrn.startswith("-"):
135            real_hrn = hrn[1:]
136            if real_hrn in list:
137                list.remove(real_hrn)
138            else:
139                print "Error:", real_hrn, "is not in researcher list:", list 
140        else:
141            if not hrn in list:
142                list.append(hrn)
143
144    dict[listname] = list
145
146 def main():
147    process_options()
148
149    # if the user didn't tell us to do much of anything, then maybe he needs
150    # some help
151    if (not infile) and (not outfile) and (not dump) and (extractgid==None):
152        showhelp()
153        return
154
155    if infile:
156        str = file(infile, "r").read()
157        record = GeniRecord(string = str)
158    else:
159        record = GeniRecord()
160
161    geni_info = record.get_geni_info()
162    geni_info_orig = geni_info.copy()
163
164    if email:
165        geni_info["email"] = email
166
167    if ip:
168        geni_info["ip"] = ip
169
170    if dns:
171        geni_info["dns"] = dns
172
173    if hrn:
174        record.name = hrn
175
176    if type:
177        record.type = type
178
179    if gidfile:
180        gid_str = file(gidfile, "r").read()
181        gid = GID(string=gid_str)
182        record.set_gid(gid)
183
184    if pubkeyfile:
185        if gidfile:
186            print "You should not use --gidfile and --pubkeyfile together"
187            sys.exit(-1)
188
189        if not record.name:
190            print "You must specify --hrn when you specify --pubkeyfile"
191            sys.exit(-1)
192
193        geni_info["create_gid"] = True
194        geni_info["create_gid_hrn"] = record.name
195        geni_info["create_gid_key"] = load_publickey_string(pubkeyfile)
196
197    if researcher:
198        update_list(geni_info, "researcher", researcher)
199
200    if (geni_info != geni_info_orig):
201        record.set_geni_info(geni_info)
202
203    errorcheck(record)
204
205    if dump:
206        record.dump(False)
207
208    if extractgid:
209        record.get_gid_object().save_to_file(extractgid, save_parents=True)
210        print "write GID to", extractgid
211
212    if outfile:
213        str = record.save_to_string()
214        file(outfile, "w").write(str)
215        print "wrote record to", outfile
216
217 if __name__=="__main__":
218    main()