bd94d0ad343113ef467bd807cc5f2161a7de239e
[aaf/authz.git] / cadi / aaf / src / main / java / org / onap / aaf / cadi / aaf / v2_0 / AAFAuthn.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.aaf.v2_0;
23
24 import java.io.IOException;
25 import java.net.URI;
26 import java.util.ArrayList;
27 import java.util.List;
28
29 import org.onap.aaf.cadi.AbsUserCache;
30 import org.onap.aaf.cadi.CachedPrincipal;
31 import org.onap.aaf.cadi.CadiException;
32 import org.onap.aaf.cadi.User;
33 import org.onap.aaf.cadi.aaf.AAFPermission;
34 import org.onap.aaf.cadi.client.Future;
35 import org.onap.aaf.cadi.client.Rcli;
36 import org.onap.aaf.cadi.lur.ConfigPrincipal;
37
38 import aaf.v2_0.CredRequest;
39
40 public class AAFAuthn<CLIENT> extends AbsUserCache<AAFPermission> {
41     private AAFCon<CLIENT> con;
42     private String realm;
43
44     /**
45      * Configure with Standard AAF properties, Stand alone
46      * @param con
47      * @throws Exception ..
48      */
49     // Package on purpose
50     AAFAuthn(AAFCon<CLIENT> con) {
51         super(con.access,con.cleanInterval,con.highCount,con.usageRefreshTriggerCount);
52         this.con = con;
53     }
54
55     /**
56      * Configure with Standard AAF properties, but share the Cache (with AAF Lur)
57      * @param con
58      * @throws Exception
59      */
60     // Package on purpose
61     AAFAuthn(AAFCon<CLIENT> con, AbsUserCache<AAFPermission> cache) {
62         super(cache);
63         this.con = con;
64     }
65
66     /**
67      * Return Native Realm of AAF Instance.
68      *
69      * @return
70      */
71     public String getRealm() {
72         return realm;
73     }
74
75     /**
76      * Returns null if ok, or an Error String;
77      *
78      * Convenience function.  Passes "null" for State object
79      */
80     public String validate(String user, String password) throws IOException {
81         return validate(user,password,null);
82     }
83
84     /**
85      * Returns null if ok, or an Error String;
86      *
87      * For State Object, you may put in HTTPServletRequest or AuthzTrans, if available.  Otherwise,
88      * leave null
89      *
90      * @param user
91      * @param password
92      * @return
93      * @throws IOException
94      * @throws CadiException
95      * @throws Exception
96      */
97     public String validate(String user, String password, Object state) throws IOException {
98         password = access.decrypt(password, false);
99         byte[] bytes = password.getBytes();
100         User<AAFPermission> usr = getUser(user,bytes);
101
102         if (usr != null && !usr.permExpired()) {
103             if (usr.principal==null) {
104                 return "User already denied";
105             } else {
106                 return null; // good
107             }
108         }
109
110         AAFCachedPrincipal cp = new AAFCachedPrincipal(user, bytes, con.cleanInterval);
111         // Since I've relocated the Validation piece in the Principal, just revalidate, then do Switch
112         // Statement
113         switch(cp.revalidate(state)) {
114             case REVALIDATED:
115                 if (usr!=null) {
116                     usr.principal = cp;
117                 } else {
118                     addUser(new User<AAFPermission>(cp,con.timeout));
119                 }
120                 return null;
121             case INACCESSIBLE:
122                 return "AAF Inaccessible";
123             case UNVALIDATED:
124                 addUser(new User<AAFPermission>(user,bytes,con.timeout));
125                 return "user/pass combo invalid for " + user;
126             case DENIED:
127                 return "AAF denies API for " + user;
128             default:
129                 return "AAFAuthn doesn't handle Principal " + user;
130         }
131     }
132
133     private class AAFCachedPrincipal extends ConfigPrincipal implements CachedPrincipal {
134         private long expires;
135         private long timeToLive;
136
137         private AAFCachedPrincipal(String name, byte[] pass, int timeToLive) {
138             super(name,pass);
139             this.timeToLive = timeToLive;
140             expires = timeToLive + System.currentTimeMillis();
141         }
142
143         public Resp revalidate(Object state) {
144             List<URI> attemptedUris = new ArrayList<>();
145             URI thisUri = null;
146             for (int retries = 0;; retries++) {
147                 try {
148                     Miss missed = missed(getName(), getCred());
149                     if (missed == null || missed.mayContinue()) {
150                         CredRequest cr = new CredRequest();
151                         cr.setId(getName());
152                         cr.setPassword(new String(getCred()));
153                         Rcli<CLIENT> client = con.clientIgnoreAlreadyAttempted(attemptedUris);
154                         thisUri = client.getURI();
155                         Future<String> fp = client.readPost("/authn/validate", con.credReqDF, cr);
156                         //Rcli<CLIENT> client = con.client().forUser(con.basicAuth(getName(), new String(getCred())));
157                         //Future<String> fp = client.read(
158                         //        "/authn/basicAuth",
159                         //        "text/plain"
160                         //       );
161                         if (fp.get(con.timeout)) {
162                             expires = System.currentTimeMillis() + timeToLive;
163                             addUser(new User<AAFPermission>(this, expires));
164                             return Resp.REVALIDATED;
165                         } else {
166                             addMiss(getName(), getCred());
167                             return Resp.UNVALIDATED;
168                         }
169                     } else {
170                         return Resp.UNVALIDATED;
171                     }
172                 } catch (Exception e) {
173                     if (thisUri != null)  {
174                         attemptedUris.add(thisUri);
175                     }
176                     con.access.log(e);
177                     if (retries > 2) {
178                         return Resp.INACCESSIBLE;
179                     }
180                 }
181             }
182         }
183
184         public long expires() {
185             return expires;
186         }
187     }
188
189 }