1 /*
  2  * Copyright © [2008-2009] Novell, Inc.  All Rights Reserved.
  3  * 
  4  * USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE DEVELOPER LICENSE AGREEMENT
  5  * OR OTHER AGREEMENT THROUGH WHICH NOVELL, INC. MAKES THE WORK AVAILABLE.  THIS WORK 
  6  * MAY NOT BE ADAPTED WITHOUT NOVELL'S PRIOR WRITTEN CONSENT.
  7  * 
  8  * NOVELL PROVIDES THE WORK "AS IS," WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 
  9  * INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR 
 10  * A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  NOVELL, THE AUTHORS OF THE WORK, AND THE 
 11  * OWNERS OF COPYRIGHT IN THE WORK ARE NOT LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 
 12  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, 
 13  * OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS IN THE WORK.
 14  */
 15 
 16 /**
 17  * @fileoverview
 18  * This file defines the Asset class, which represents enterprise assets that might be referenced in events.
 19  * This asset information is stored in the Sentinel database and is attached to inbound
 20  * events as referential metadata which can be accessed by right-click menu functions.
 21  * @name Asset Class
 22  */
 23 
 24 /**
 25  * Constructs an instance of the Asset class which represents objects managed by Sentinel.
 26  * @example
 27  * var asset1 = new Asset();
 28  * asset.Description = "Main web server";
 29  * asset.IPv4 = "10.0.0.23";
 30  * var asset2 = new Asset({IPv4:"10.0.0.24",Vendor:"Novell"});
 31  * asset2.MAC = "0f:34:23:12:56:23";
 32  * asset.save();
 33  * asset2.save();
 34  * @class
 35  * The Asset class provides methods to store asset information representing enterprise
 36  * assets. This asset information is used to provide additional metadata to aid in analysis
 37  * of inbound events; the mapping service is used to "attach" asset information to these events.
 38  * The class accepts a pre-defined set of asset attributes:
 39  * <ul>
 40  * <li>GUID {GUID} : Unique identifier for this asset (assigned by Sentinel)
 41  * <li>IPv4* {String} : The IPv4 address of the asset, in dotted-quad notation; this is required
 42  * <li>IPv6 {String} : The IPv6 address of the asset (eight groups of four hex digits, colon-separated)
 43  * <li>Customer* {Customer} : The customer who owns this asset (defines a namespace)
 44  * <li>Hostname {String} : The hostname of the asset as provided by a name service (DNS, WINS)
 45  * <li>MAC {String} : The MAC address of the asset (hex pairs, colon separated)
 46  * <li>Category^ {String} : The class of asset being described (server|desktop|laptop|etc)
 47  * <li>Description {String} : A readable description of the asset
 48  * <li>Value {String} : The value of the asset, in terms of currency
 49  * <li>Criticality^ {String} : The criticality rating of the asset (low|med|high)
 50  * <li>Vendor {String} : The vendor which provides this asset
 51  * <li>Product {String} : The product name of this asset
 52  * <li>Version {String} : The product version of this asset
 53  * <li>Owner {Identity} : The owner of this asset
 54  * <li>Maintainer {Identity} : The maintainer of this asset
 55  * <li>BusinessUnit {String} : The business unit which holds this asset
 56  * <li>Department^ {String} : The department which holds this asset
 57  * <li>Location {String} : The location at which this asset is located; use internal codes or full address
 58  * <li>Coordinates {Coordinates} : The latitude/longitude coordinates of the asset (not yet implemented)
 59  * </ul>
 60  * * : This field is used as a key field for mapping metadata into the event
 61  * ^ : This field is copied into the raw event structure for use in correlation. Other fields are
 62  * available via lookup for reporting.
 63  * 
 64  * @author   Novell Engineering
 65  * @version  6.1
 66  * @param {Object} properties  Set of pre-defined properties used to initialize this object
 67  * @constructor
 68  */
 69 function Asset(properties) {
 70 	if( typeof properties != "undefined") {
 71 		// Poor man's Impl
 72 		for (var field in properties) {
 73 			if (typeof AssetImpl[field] != "undefined") {
 74 				this[field] = properties[field];
 75 			}
 76 		}
 77 	}
 78 	return true;
 79 	
 80 	// Never accessed, but defined here for documentation
 81 	
 82 	/**
 83 	 * Unique identifier for this asset (assigned by Sentinel).
 84 	 * @type UUID
 85 	 */
 86 	this.GUID;
 87 	
 88 	/**
 89 	 * The IPv4 address of the asset, in dotted-quad notation (leave blank for dynamic address allocation).
 90 	 * Used as a key field when matching against event data. One of Hostname or IPv4 are required.
 91 	 * @type String
 92 	 */
 93 	this.IPv4; 
 94 	
 95 	/**
 96 	 * The IPv6 address of the asset (eight groups of four hex digits, colon-separated).
 97 	 * @type String
 98 	 */
 99 	this.IPv6;
100 	
101 	/**
102 	 * The tenant who owns this asset (defines a namespace).
103 	 * This field will typically be set based on the TenantName parameter for the Collector,
104 	 * unless the Collector processes data from multiple tenant. It should match the TenantName 
105 	 * injected into event data based on event Collectors' TenantName parameter.
106 	 * Used as a key field when matching against event data.
107 	 * @example
108 	 * var asset = new Asset(); 
109 	 * asset.Tenant = "NetIQ";
110 	 * @type String
111 	 */
112 	this.Tenant;
113 	
114 	/**
115 	 * The hostname of the asset as provided by a name service (DNS, WINS). One of Hostname or IPv4 are required.
116 	 * @type String
117 	 */
118 	this.Hostname;
119 	
120 	/**
121 	 * The MAC address of the asset (hex pairs, colon separated)
122 	 * @type String
123 	 */
124 	this.MAC;
125 	
126 	/**
127 	 * The class of asset being described. Novell recommends developing an enumerated list of asset
128 	 * categories (such as server|desktop|laptop|etc) and restricting this field to those possibilities.
129 	 * This will allow for easier correlation based on the asset category.
130 	 * This field is injected into events if the assets referenced in the event matches.
131 	 * @type String
132 	 */
133 	this.Category;
134 	
135 	/**
136 	 * A readable description of the asset.
137 	 * @type String
138 	 */
139 	this.Description;
140 	
141 	/**
142 	 * The value of the asset, in terms of currency. Novell recommends normalizing to a specific
143 	 * currency so that numeric tests can be applied in correlation.
144 	 * @type String
145 	 */
146 	this.Value;
147 	
148 	/**
149 	 * The criticality rating of the asset (low|med|high). Novell recommends developing an enumerated list of asset
150 	 * criticalities (such as low|med|high) and restricting this field to those possibilities.
151 	 * This will allow for easier correlation based on the asset criticality.
152 	 * This field is injected into events if the assets referenced in the event matches.
153 	 * @type String
154 	 */
155 	this.Criticality;
156 	
157 	/**
158 	 * The vendor which provides this asset.
159 	 * @type String
160 	 */
161 	this.Vendor;
162 	
163 	/**
164 	 * The product name of this asset.
165 	 * @type String
166 	 */
167 	this.Product;
168 	
169 	/**
170 	 * The product version of this asset.
171 	 * @type String
172 	 */
173 	this.Version;
174 	
175 	/**
176 	 * The owner of this asset. Note that this is an Identity, so you must find the Identity before
177 	 * you can set this field.
178 	 * @example
179 	 * var asset = new Asset();
180 	 * var myIdens = Identity.find({PrimaryEmail : "user1@novell.com"});
181 	 * if (myIdens.length() == 1) { 
182 	 * 	asset.Owner = myIdens[0];
183 	 * }
184 	 * @type Identity
185 	 */
186 	this.Owner;
187 
188 	/**
189 	 * The maintainer of this asset. Note that this is an Identity, so you must find the Identity before
190 	 * you can set this field.
191 	 * @example
192 	 * var asset = new Asset();
193 	 * var myIdens = Identity.find({PrimaryEmail : "user2@novell.com"});
194 	 * if (myIdens.length() == 1) { 
195 	 * 	asset.Maintainer = myIdens[0];
196 	 * }
197 	 * @type Identity
198 	 */
199 	this.Maintainer;
200  
201 	/**
202 	 * The business unit which holds this asset.
203 	 * @type String
204 	 */
205 	this.BusinessUnit;
206 	
207 	/**
208 	 * The department which holds this asset.
209 	 * This field is injected into events if the assets referenced in the event matches.
210 	 * @type String
211 	 */
212 	this.Department;
213 	
214 	/**
215 	 * The location at which this asset is located; use internal codes or full address.
216 	 * @type String
217 	 */
218 	this.Location;
219 	
220 	/**
221 	 * The latitude/longitude coordinates of the asset (not yet implemented).
222 	 * @type Coordinates
223 	 */
224 	this.Coordinates;
225 };
226 
227 // Used as a reference for what attributes are allowed
228 AssetImpl = {"IPv4":null,"IPv6":null,"Tenant":null,"Hostname":null,"MAC":null,
229 	"Category":null,"Description":null,"Value":null,"Criticality":null,"Vendor":null,
230 	"Product":null,"Version":null,"BusinessUnit":null,"Department":null,"Location":null,
231 	"Coordinates":null};
232 
233 
234 /**
235 * This method saves the Asset object in the Sentinel database.
236 * <p>Example:
237 * <pre>
238 * this.testasset = new Asset({"Hostname":"testname","IPv4":"10.0.0.12"});
239 * this.testasset.save();
240 * </pre> 
241 * @return {Boolean} Result  Result of the attempted save.
242 */
243 Asset.prototype.save = function() {
244 	
245 	/*
246 	 * This method will use the following translation between the JS Asset object and the Sentinel "infoblock" fields:
247 	 * [JS Asset attribute] -> [Infoblock tag]
248 	 * GUID -> EnvironmentIdentity
249 	 * IPv4 -> IpAddress
250 	 * IPv6 -> NetworkIdentity
251 	 * Tenant -> CustomerName 
252 	 * Hostname -> HostName
253 	 * MAC -> MacAddress
254 	 * Category -> AssetCategory
255 	 * Description -> AssetName
256 	 * Value -> AssetValue
257 	 * Criticality -> Criticality
258 	 * Vendor -> Vendor
259 	 * Product -> ProductName
260 	 * Version -> ProductVersion
261 	 * Owner.PrimaryEmail -> OwnerEmail
262 	 * Owner.FirstName -> OwnerFirstName
263 	 * Owner.LastName -> OwnerLastName
264 	 * Owner.PrimaryPhone -> OwnerPhoneNumber
265 	 * Owner.IdentityGuid -> Room  (We are "faking" an FK over to Identity)
266 	 * Maintainer.PrimaryEmail -> MaintainerEmail
267 	 * Maintainer.FirstName -> MaintainerFirstName
268 	 * Maintainer.LastName -> MaintainerLastName
269 	 * Maintainer.PrimaryPhone -> MaintainerPhoneNumber
270 	 * Maintainer.IdentityGuid -> RackNumber (We are "faking" an FK over to Identity)
271 	 * BusinessUnit -> BusinessUnit
272 	 * Department -> Department
273 	 * Location -> AddressLine1
274 	 * Coordinates -> AddressLine2
275 	 * AssetEntryType will be hardcoded to "physical"
276 	 */
277 	
278 	// Must have one of these set
279 	if (!this.IPv4 || !(/^\d+\.\d+\.\d+\.\d+$/.test(this.IPv4) )) {
280 		log("Attempt to save an asset without a valid IP address");
281 		return false;
282 	}
283 	
284 	var owneremail,ownerfirst,ownerlast,ownerphone,ownerguid;
285 	var maintaineremail,maintainerfirst,maintainerlast,maintainerphone,maintainerguid;
286 	
287 	// For some strange reason, First/Last must be unique or later records will overwrite this one
288 	if (this.Owner instanceof IdentityImpl && this.Owner.PrimaryEmail && this.Owner.PrimaryEmail != "") {
289 		owneremail = this.Owner.PrimaryEmail;
290 		ownerfirst = (!this.Owner.FirstName || this.Owner.FirstName == "null") ? this.Owner.PrimaryEmail.split("@")[0] : this.Owner.FirstName;
291 		ownerlast = (!this.Owner.LastName || this.Owner.LastName == "null") ? this.Owner.PrimaryEmail.split("@")[1] : this.Owner.LastName;
292 		ownerphone = this.Owner.PrimaryPhone == "null" ? "" : this.Owner.PrimaryPhone;
293 		ownerguid = this.Owner.IdentityGuid;
294 	}
295 	
296 	if (this.Maintainer instanceof IdentityImpl && this.Maintainer.PrimaryEmail && this.Maintainer.PrimaryEmail != "") {
297 		maintaineremail = this.Maintainer.PrimaryEmail;
298 		maintainerfirst = (!this.Maintainer.FirstName || this.Maintainer.FirstName == "null") ? this.Maintainer.PrimaryEmail.split("@")[0] : this.Maintainer.FirstName;
299 		maintainerlast = (!this.Maintainer.LastName || this.Maintainer.LastName == "null") ? this.Maintainer.PrimaryEmail.split("@")[1] : this.Maintainer.LastName;
300 		maintainerphone = this.Maintainer.PrimaryPhone == "null" ? "" : this.Maintainer.PrimaryPhone;
301 		maintainerguid = this.Maintainer.IdentityGuid;
302 	}
303 	
304 	var infoSession = new InfoBlockSession("asset", new ContextInfoSender(instance.CONFIG.scriptContext));
305 	
306 	if (typeof this.GUID == "undefined") {
307 		//this.GUID = new Date.UTC();
308 	}
309 	
310 	var fields = new Array("AssetEntryType","EnvironmentIdentity","IpAddress","NetworkIdentity","TenantName",
311 			"HostName","MacAddress","AssetCategory","AssetName","AssetValue","Criticality",
312 			"Vendor","ProductName","ProductVersion",
313 			"OwnerEmail","OwnerFirstName","OwnerLastName","OwnerPhoneNumber","Room",
314 			"MaintainerEmail","MaintainerFirstName","MaintainerLastName","MaintainerPhoneNumber","RackNumber",
315 			"BusinessUnit","Department","AddressLine1","AddressLine2");
316 	var values = new Array("physical",this.GUID,this.IPv4,this.IPv6,this.Tenant ? this.Tenant.Name : "unknown",
317 			this.Hostname,this.MAC,this.Category,this.Description,this.Value,this.Criticality,
318 			this.Vendor,this.Product,this.Version,
319 			owneremail,ownerfirst,ownerlast,ownerphone,ownerguid,
320 			maintaineremail,maintainerfirst,maintainerlast,maintainerphone,maintainerguid,
321 			this.BusinessUnit,this.Department,this.Location,this.Coordinates);
322 	
323 	var Jfields = fields.toJava(java.lang.String);
324 	var Jvalues = values.toJava(java.lang.String);
325 	
326 	infoSession.setTag(Jfields, Jvalues );
327 	
328 	infoSession.push();
329 	infoSession.send();
330 	infoSession.close();
331 };
332 
333 /**
334  * Finds the asset(s) in the Sentinel database.
335  * NOT YET IMPLEMENTED.
336  * @return {Asset[]}  Matching assets.
337  */
338 Asset.prototype.find = function() {
339 	return null;
340 };