]> WPIA git - cassiopeia.git/blob - src/db/psql.cpp
change to postgres with libpqxx
[cassiopeia.git] / src / db / psql.cpp
1 #include "psql.h"
2
3 #include <stdio.h>
4
5 #include <iostream>
6
7 #include <log/logger.hpp>
8
9 PostgresJobProvider::PostgresJobProvider( const std::string& server, const std::string& user, const std::string& password, const std::string& database ):
10     c("dbname="+database+" host="+server+" user="+user+" password="+password){
11     // TODO better connection string generation??
12 }
13
14
15 std::shared_ptr<Job> PostgresJobProvider::fetchJob() {
16     std::string q = "SELECT id, \"targetId\", task, \"executeFrom\", \"executeTo\", warning FROM jobs WHERE state='open' AND warning < 3";
17     pqxx::work txn(c);
18     pqxx::result result = txn.exec(q);
19
20
21     auto job = std::make_shared<Job>();
22
23     if( result.size() == 0 ) {
24         return nullptr;
25     }
26
27     job->id = result[0]["id"].as<std::string>();
28     job->target =  result[0]["\"targetId\""].as<std::string>();
29     job->task = result[0]["task"].as<std::string>();
30     job->from = result[0]["\"executeFrom\""].as<std::string>("");
31     job->to = result[0]["\"executeTo\""].as<std::string>("");
32     job->warning = result[0]["warning"].as<std::string>();
33
34     logger::notef( "Got a job: (id=%s, target=%s, task=%s, from=%s, to=%s, warnings=%s)", job->id, job->target, job->task, job->from, job->to, job->warning );
35
36     return job;
37 }
38
39 void PostgresJobProvider::finishJob( std::shared_ptr<Job> job ) {
40     pqxx::work txn(c);
41
42     std::string q = "UPDATE jobs SET state='done' WHERE id=" + txn.quote( job->id );
43     pqxx::result r = txn.exec(q);
44
45     if( r.affected_rows() != 1 ) {
46         throw "No database entry found.";
47     }
48     txn.commit();
49 }
50
51 void PostgresJobProvider::failJob( std::shared_ptr<Job> job ) {
52     pqxx::work txn(c);
53
54     std::string q = "UPDATE jobs SET warning = warning + 1 WHERE id=" + txn.quote( job->id );
55     pqxx::result r = txn.exec(q);
56
57     if( r.affected_rows() != 1 ) {
58         throw "No database entry found.";
59     }
60     txn.commit();
61 }
62
63 std::shared_ptr<TBSCertificate> PostgresJobProvider::fetchTBSCert( std::shared_ptr<Job> job ) {
64     pqxx::work txn(c);
65     auto cert = std::make_shared<TBSCertificate>();
66     std::string q = "SELECT md, profile, csr_name, csr_type, keyname FROM certs INNER JOIN profiles ON profiles.id = certs.profile WHERE certs.id=" + txn.quote( job->target );
67     pqxx::result r = txn.exec(q);
68
69     if( r.size() != 1 ) {
70         throw "Error, no or multiple certs found";
71      }
72     auto ro = r[0];
73
74     std::string profileName = ro["keyname"].as<std::string>();
75
76     cert->md = ro["md"].as<std::string>();
77     std::string profileId = ro["profile"].as<std::string>();
78
79     while( profileId.size() < 4 ) {
80         profileId = "0" + profileId;
81     }
82
83     cert->profile = profileId + "-" + profileName;
84
85     cert->csr = ro["csr_name"].as<std::string>();
86     cert->csr_type = ro["csr_type"].as<std::string>();
87
88     cert->SANs = std::vector<std::shared_ptr<SAN>>();
89
90     q = "SELECT contents, type FROM \"subjectAlternativeNames\" WHERE \"certId\"=" + txn.quote( job->target );
91     r = txn.exec( q );
92
93     std::cout << "Fetching SANs" << std::endl;
94
95     for( auto row = r.begin(); row != r.end(); ++row) {
96         auto nSAN = std::make_shared<SAN>();
97         nSAN->content = row["contents"].as<std::string>();
98         nSAN->type = row["type"].as<std::string>();
99         cert->SANs.push_back( nSAN );
100     }
101
102     q = "SELECT name, value FROM \"certAvas\" WHERE \"certId\"=" + txn.quote( job->target );
103     r = txn.exec( q );
104
105     for( auto row = r.begin(); row != r.end(); ++row) {
106         auto nAVA = std::make_shared<AVA>();
107         nAVA->name = row["name"].as<std::string>();
108         nAVA->value = row["value"].as<std::string>();
109         cert->AVAs.push_back( nAVA );
110     }
111
112     return cert;
113 }
114
115 std::string pgTime( std::string isoTime){
116         return isoTime.substr(0, 8) + " " + isoTime.substr(8, 6);
117 }
118
119 void PostgresJobProvider::writeBack( std::shared_ptr<Job> job, std::shared_ptr<SignedCertificate> res ) {
120     pqxx::work txn(c);
121     std::string id = "SELECT id FROM cacerts WHERE keyname=" + txn.quote( res->ca_name );
122     pqxx::result r = txn.exec(id);
123
124     std::string read_id;
125
126     if( r.size() != 1) {
127         throw "Error while inserting new ca cert not found";
128     } else {
129         read_id = r[0]["id"].as<std::string>();
130     }
131
132     std::string q = "UPDATE certs SET crt_name=" + txn.quote( res->crt_name ) + ", serial=" + txn.quote( res->serial ) + ", \"caid\" = " + txn.quote( read_id ) + ", created=" + txn.quote( pgTime(res->before) ) + ", expire=" + txn.quote( pgTime(res->after) ) + "  WHERE id=" + txn.quote( job->target );
133     // TODO write more thingies back
134
135     r = txn.exec( q );
136     if( r.affected_rows() != 1 ){
137         throw "Only one row should be updated.";
138     }
139     txn.commit();
140 }
141
142 std::pair<std::string, std::string> PostgresJobProvider::getRevocationInfo( std::shared_ptr<Job> job ) {
143     return {"",""};
144     pqxx::work txn(c);
145     std::string q = "SELECT certs.serial, cacerts.keyname FROM certs INNER JOIN cacerts ON certs.\"caId\" = cacerts.id WHERE certs.id = " + txn.quote( job->target );
146
147     pqxx::result r = txn.exec( q );
148     if( r.size() != 1) {
149         throw "Only one row expected but multiple found.";
150     }
151
152     
153     return {r[0][0].as<std::string>(), r[0][1].as<std::string>()};
154 }
155
156 void PostgresJobProvider::writeBackRevocation( std::shared_ptr<Job> job, std::string date ) {
157     pqxx::work txn(c);
158     pqxx::result r = txn.exec( "UPDATE certs SET revoked = " + txn.quote( date ) + " WHERE id = " + txn.quote( job->target ) );
159     if( r.affected_rows() != 1 ){
160         throw "Only one row should be updated.";
161     }
162     txn.commit();
163 }