Add a MassMail Batch Program
[aaf/authz.git] / cadi / core / src / main / java / org / onap / aaf / cadi / filter / MapBathConverter.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.filter;
23
24 import java.io.IOException;
25 import java.text.ParseException;
26 import java.text.SimpleDateFormat;
27 import java.util.Date;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.TreeMap;
31
32 import org.onap.aaf.cadi.Access;
33 import org.onap.aaf.cadi.Access.Level;
34 import org.onap.aaf.cadi.CadiException;
35 import org.onap.aaf.cadi.Symm;
36 import org.onap.aaf.cadi.util.CSV;
37 import org.onap.aaf.cadi.util.CSV.Visitor;
38 import org.onap.aaf.cadi.util.Holder;
39
40 /**
41  * This Filter is designed to help MIGRATE users from systems that don't match the FQI style.
42  *
43  * Style 1, where just the ID is translated, i.e. OLD => new@something.onap.org, that is acceptable
44  * longer term, because it does not store Creds locally.  The passwords are in appropriate systems, but
45  * it's still painful operationally, though it does ease migration.
46  *
47  * Style 3, however, which is Direct match of Authorization Header to replacement, is only there
48  * because some passwords are simply not acceptable for AAF, (too easy, for instance), and it is
49  * not feasible to break Organization Password rules for a Migration.  Therefore, this method
50  * should not considered something that is in any way a permanent
51  *
52
53  *
54  * It goes without saying that any file with the password conversion should be protected by "400", etc.
55  *
56  * @author Instrumental (Jonathan)
57  *
58  */
59 public class MapBathConverter {
60     private static final String BASIC = "Basic ";
61     private final Map<String,String> map;
62
63     /**
64      * Create with colon separated name value pairs
65      *  Enter the entire "Basic dXNlcjpwYXNz" "Authorization" header, where "dXNlcjpwYXNz" is
66      *  base64 encoded, which can be created with "cadi" tool (in jar)
67      *
68      *  The replacement should also be an exact replacement of what you want.  Recognize that
69      *  this should be TEMPORARY as you are storing credentials outside the users control.
70      *
71      * @param value
72      * @throws IOException
73      * @throws CadiException
74      */
75     public MapBathConverter(final Access access, final CSV csv) throws IOException, CadiException {
76         map = new TreeMap<>();
77         final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
78         final Date now = new Date();
79         csv.visit(new Visitor() {
80             @Override
81             public void visit(List<String> row) throws CadiException {
82                 if(row.size()<3) {
83                     throw new CadiException("CSV file " + csv + " must have at least 2 Basic Auth columns and an Expiration Date(YYYY-MM-DD) in each row");
84                 }
85                 try {
86                     Date date = sdf.parse(row.get(2));
87                     String oldID = row.get(0);
88                     String newID = row.get(1);
89                     if(date.after(now)) {
90                         if(!oldID.startsWith(BASIC) && newID.startsWith(BASIC)) {
91                             throw new CadiException("CSV file " + csv + ": Uncredentialed ID " + idFromBasic(oldID,null) +
92                                                     " may not transfer to credentialed ID " + idFromBasic(newID,null));
93                         } else {
94                             map.put(oldID,newID);
95                             access.printf(Level.INIT, "ID Conversion from %s to %s enabled",
96                                     idFromBasic(oldID,null),
97                                     idFromBasic(newID,null));
98                         }
99                     } else {
100                         access.printf(Level.INIT, "ID Conversion from %s to %s has expired.",
101                                 idFromBasic(oldID,null),
102                                 idFromBasic(newID,null));
103                     }
104                 } catch (ParseException e) {
105                     throw new CadiException("Cannot Parse Date: " + row.get(2));
106                 } catch (IOException e) {
107                     throw new CadiException(e);
108                 }
109             }
110         });
111     }
112
113     private static String idFromBasic(String bath, Holder<String> hpass) throws IOException, CadiException {
114         if(bath.startsWith(BASIC)) {
115             String cred = Symm.base64noSplit.decode(bath.substring(6));
116             int colon = cred.indexOf(':');
117             if(colon<0) {
118                 throw new CadiException("Invalid Authentication Credential for " + cred);
119             }
120             if(hpass!=null) {
121                 hpass.set(cred.substring(colon+1));
122             }
123             return cred.substring(0, colon);
124         } else {
125             return bath;
126         }
127     }
128
129     /**
130      * use to instantiate entries
131      *
132      * @return
133      */
134     public Map<String,String> map() {
135         return map;
136     }
137
138     public String convert(Access access, final String bath) {
139         String rv = map.get(bath);
140
141         String cred;
142         String tcred=null;
143         Holder<String> hpass=null;
144         try {
145             if(bath.startsWith(BASIC)) {
146                 cred = idFromBasic(bath,(hpass=new Holder<String>(null)));
147                 if(rv==null) {
148                     rv = map.get(cred);
149                 }
150             } else {
151                 cred = bath;
152             }
153
154             if(rv==null) {
155                 // Nothing here, just return original
156                 rv = bath;
157             } else {
158                 if(rv.startsWith(BASIC)) {
159                     tcred = idFromBasic(rv,null);
160                 } else {
161                     if(hpass!=null) {
162                         tcred = rv;
163                         rv = BASIC + Symm.base64noSplit.encode(rv+':'+hpass.get());
164                     }
165                 }
166                 if(tcred != null) {
167                     access.printf(Level.AUDIT, "ID %s converted to %s",cred,tcred);
168                 }
169             }
170         } catch (IOException | CadiException e) {
171             access.log(e,"Invalid Authorization");
172         }
173         return rv==null?bath:rv;
174     }
175 }