3669d04faf4a0dc198674ca8e4c446f25c69e578
[aaf/authz.git] / cadi / aaf / src / main / java / org / onap / aaf / cadi / cm / ArtifactDir.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  * ===========================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END====================================================
19  *
20  */
21
22 package org.onap.aaf.cadi.cm;
23
24 import java.io.File;
25 import java.io.FileOutputStream;
26 import java.io.FileWriter;
27 import java.io.IOException;
28 import java.io.PrintStream;
29 import java.io.PrintWriter;
30 import java.security.KeyStore;
31 import java.util.ArrayList;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35
36 import org.onap.aaf.cadi.CadiException;
37 import org.onap.aaf.cadi.Symm;
38 import org.onap.aaf.cadi.config.Config;
39 import org.onap.aaf.cadi.util.Chmod;
40 import org.onap.aaf.misc.env.Trans;
41 import org.onap.aaf.misc.env.util.Chrono;
42
43 import certman.v1_0.Artifacts.Artifact;
44 import certman.v1_0.CertInfo;
45
46 public abstract class ArtifactDir implements PlaceArtifact {
47
48         protected static final String C_R = "\n";
49         protected File dir;
50         private List<String> encodeds = new ArrayList<String>();
51         
52         private Symm symm;
53         // This checks for multiple passes of Dir on the same objects.  Run clear after done.
54         protected static Map<String,Object> processed = new HashMap<String,Object>();
55
56
57         /**
58          * Note:  Derived Classes should ALWAYS call "super.place(cert,arti)" first, and 
59          * then "placeProperties(arti)" just after they implement
60          */
61         @Override
62         public final boolean place(Trans trans, CertInfo certInfo, Artifact arti, String machine) throws CadiException {
63                 validate(arti);
64                 
65                 try {
66                         // Obtain/setup directory as required
67                         dir = new File(arti.getDir());
68                         if(processed.get("dir")==null) {
69                                 if(!dir.exists()) {
70                                         Chmod.to755.chmod(dir);
71                                         if(!dir.mkdirs()) {
72                                                 throw new CadiException("Could not create " + dir);
73                                         }
74                                 }
75                                 
76                                 // Also place cm_url and Host Name
77                                 addProperty(Config.CM_URL,trans.getProperty(Config.CM_URL));
78                                 addProperty(Config.HOSTNAME,machine);
79                                 addProperty(Config.AAF_ENV,certInfo.getEnv());
80                                 // Obtain Issuers
81                                 boolean first = true;
82                                 StringBuilder issuers = new StringBuilder();
83                                 for(String dn : certInfo.getCaIssuerDNs()) {
84                                         if(first) {
85                                                 first=false;
86                                         } else {
87                                                 issuers.append(':');
88                                         }
89                                         issuers.append(dn);
90                                 }
91                                 addProperty(Config.CADI_X509_ISSUERS,issuers.toString());
92                         }
93                         symm = (Symm)processed.get("symm");
94                         if(symm==null) {
95                                 // CADI Key Gen
96                                 File f = new File(dir,arti.getNs() + ".keyfile");
97                                 if(!f.exists()) {
98                                         write(f,Chmod.to400,Symm.keygen());
99                                 }
100                                 symm = Symm.obtain(f); 
101
102                                 addEncProperty("ChallengePassword", certInfo.getChallenge());
103                                 
104                                 processed.put("symm",symm);
105                         }
106
107                         _place(trans, certInfo,arti);
108                         
109                         placeProperties(arti);
110                         
111                         processed.put("dir",dir);
112
113                 } catch (Exception e) {
114                         throw new CadiException(e);
115                 }
116                 return true;
117         }
118
119         /**
120          * Derived Classes implement this instead, so Dir can process first, and write any Properties last
121          * @param cert
122          * @param arti
123          * @return
124          * @throws CadiException
125          */
126         protected abstract boolean _place(Trans trans, CertInfo certInfo, Artifact arti) throws CadiException;
127
128         protected void addProperty(String tag, String value) throws IOException {
129                 StringBuilder sb = new StringBuilder();
130                 sb.append(tag);
131                 sb.append('=');
132                 sb.append(value);
133                 encodeds.add(sb.toString());
134         }
135
136         protected void addEncProperty(String tag, String value) throws IOException {
137                 StringBuilder sb = new StringBuilder();
138                 sb.append(tag);
139                 sb.append('=');
140                 sb.append("enc:");
141                 sb.append(symm.enpass(value));
142                 encodeds.add(sb.toString());
143         }
144
145         protected void write(File f, Chmod c, String ... data) throws IOException {
146                 f.setWritable(true,true);
147                 
148                 FileOutputStream fos = new FileOutputStream(f);
149                 PrintStream ps = new PrintStream(fos);
150                 try {
151                         for(String s : data) {
152                                 ps.print(s);
153                         }
154                 } finally {
155                         ps.close();
156                         c.chmod(f);
157                 }
158         }
159
160         protected void write(File f, Chmod c, byte[] bytes) throws IOException {
161                 f.setWritable(true,true);
162                 
163                 FileOutputStream fos = new FileOutputStream(f);
164                 try {
165                         fos.write(bytes);
166                 } finally {
167                         fos.close();
168                         c.chmod(f);
169                 }
170         }
171         
172         protected void write(File f, Chmod c, KeyStore ks, char[] pass ) throws IOException, CadiException {
173                 f.setWritable(true,true);
174                 
175                 FileOutputStream fos = new FileOutputStream(f);
176                 try {
177                         ks.store(fos, pass);
178                 } catch (Exception e) {
179                         throw new CadiException(e);
180                 } finally {
181                         fos.close();
182                         c.chmod(f);
183                 }
184         }
185
186
187         private void validate(Artifact a) throws CadiException {
188                 StringBuilder sb = new StringBuilder();
189                 if(a.getDir()==null) {
190                         sb.append("File Artifacts require a path");
191                 }
192
193                 if(a.getNs()==null) {
194                         if(sb.length()>0) {
195                                 sb.append('\n');
196                         }
197                         sb.append("File Artifacts require an AAF Namespace");
198                 }
199                 
200                 if(sb.length()>0) {
201                         throw new CadiException(sb.toString());
202                 }
203         }
204
205         private boolean placeProperties(Artifact arti) throws CadiException {
206                 if(encodeds.size()==0) {
207                         return true;
208                 }
209                 boolean first=processed.get("dir")==null;
210                 try {
211                         File f = new File(dir,arti.getNs()+".props");
212                         if(f.exists()) {
213                                 if(first) {
214                                         f.delete();
215                                 } else {
216                                         f.setWritable(true);
217                                 }
218                         }
219                         // Append if not first
220                         PrintWriter pw = new PrintWriter(new FileWriter(f,!first));
221                         
222                         // Write a Header
223                         if(first) {
224                                 for(int i=0;i<60;++i) {
225                                         pw.print('#');
226                                 }
227                                 pw.println();
228                                 pw.println("# Properties Generated by AT&T Certificate Manager");
229                                 pw.print("#   by ");
230                                 pw.println(System.getProperty("user.name"));
231                                 pw.print("#   on ");
232                                 pw.println(Chrono.dateStamp());
233                                 pw.println("# @copyright 2016, AT&T");
234                                 for(int i=0;i<60;++i) {
235                                         pw.print('#');
236                                 }
237                                 pw.println();
238                                 for(String prop : encodeds) {
239                                         if(    prop.startsWith("cm_") 
240                                                 || prop.startsWith(Config.HOSTNAME)
241                                                 || prop.startsWith(Config.AAF_ENV)) {
242                                                 pw.println(prop);
243                                         }
244                                 }
245                         }
246                         
247                         try {
248                                 for(String prop : encodeds) {
249                                         if(prop.startsWith("cadi")) {
250                                                 pw.println(prop);
251                                         }
252                                 }
253                         } finally {
254                                 pw.close();
255                         }
256                         Chmod.to644.chmod(f);
257                         
258                         if(first) {
259                                 // Challenge
260                                 f = new File(dir,arti.getNs()+".chal");
261                                 if(f.exists()) {
262                                         f.delete();
263                                 }
264                                 pw = new PrintWriter(new FileWriter(f));
265                                 try {
266                                         for(String prop : encodeds) {
267                                                 if(prop.startsWith("Challenge")) {
268                                                         pw.println(prop);
269                                                 }
270                                         }
271                                 } finally {
272                                         pw.close();
273                                 }
274                                 Chmod.to400.chmod(f);
275                         }
276                 } catch(Exception e) {
277                         throw new CadiException(e);
278                 }
279                 return true;
280         }
281         
282         public static void clear() {
283                 processed.clear();
284         }
285
286 }