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 customer who owns this asset (defines a namespace). 103 * This field will typically be set based on the MSSP Customer Name parameter for the Collector, 104 * unless the Collector processes data from multiple customers. It should match the Customer 105 * injected into event data based on event Collectors' MSSP Customer Name parameter. 106 * Used as a key field when matching against event data. 107 * @example 108 * var asset = new Asset(); 109 * var id = Customer.getId(custname); 110 * asset.CustomerID = id; 111 * @type String 112 */ 113 this.Customer; 114 115 /** 116 * The hostname of the asset as provided by a name service (DNS, WINS). One of Hostname or IPv4 are required. 117 * @type String 118 */ 119 this.Hostname; 120 121 /** 122 * The MAC address of the asset (hex pairs, colon separated) 123 * @type String 124 */ 125 this.MAC; 126 127 /** 128 * The class of asset being described. Novell recommends developing an enumerated list of asset 129 * categories (such as server|desktop|laptop|etc) and restricting this field to those possibilities. 130 * This will allow for easier correlation based on the asset category. 131 * This field is injected into events if the assets referenced in the event matches. 132 * @type String 133 */ 134 this.Category; 135 136 /** 137 * A readable description of the asset. 138 * @type String 139 */ 140 this.Description; 141 142 /** 143 * The value of the asset, in terms of currency. Novell recommends normalizing to a specific 144 * currency so that numeric tests can be applied in correlation. 145 * @type String 146 */ 147 this.Value; 148 149 /** 150 * The criticality rating of the asset (low|med|high). Novell recommends developing an enumerated list of asset 151 * criticalities (such as low|med|high) and restricting this field to those possibilities. 152 * This will allow for easier correlation based on the asset criticality. 153 * This field is injected into events if the assets referenced in the event matches. 154 * @type String 155 */ 156 this.Criticality; 157 158 /** 159 * The vendor which provides this asset. 160 * @type String 161 */ 162 this.Vendor; 163 164 /** 165 * The product name of this asset. 166 * @type String 167 */ 168 this.Product; 169 170 /** 171 * The product version of this asset. 172 * @type String 173 */ 174 this.Version; 175 176 /** 177 * The owner of this asset. Note that this is an Identity, so you must find the Identity before 178 * you can set this field. 179 * @example 180 * var asset = new Asset(); 181 * var myIdens = Identity.find({PrimaryEmail : "user1@novell.com"}); 182 * if (myIdens.length() == 1) { 183 * asset.Owner = myIdens[0]; 184 * } 185 * @type Identity 186 */ 187 this.Owner; 188 189 /** 190 * The maintainer of this asset. Note that this is an Identity, so you must find the Identity before 191 * you can set this field. 192 * @example 193 * var asset = new Asset(); 194 * var myIdens = Identity.find({PrimaryEmail : "user2@novell.com"}); 195 * if (myIdens.length() == 1) { 196 * asset.Maintainer = myIdens[0]; 197 * } 198 * @type Identity 199 */ 200 this.Maintainer; 201 202 /** 203 * The business unit which holds this asset. 204 * @type String 205 */ 206 this.BusinessUnit; 207 208 /** 209 * The department which holds this asset. 210 * This field is injected into events if the assets referenced in the event matches. 211 * @type String 212 */ 213 this.Department; 214 215 /** 216 * The location at which this asset is located; use internal codes or full address. 217 * @type String 218 */ 219 this.Location; 220 221 /** 222 * The latitude/longitude coordinates of the asset (not yet implemented). 223 * @type Coordinates 224 */ 225 this.Coordinates; 226 }; 227 228 // Used as a reference for what attributes are allowed 229 AssetImpl = {"IPv4":null,"IPv6":null,"Customer":null,"Hostname":null,"MAC":null, 230 "Category":null,"Description":null,"Value":null,"Criticality":null,"Vendor":null, 231 "Product":null,"Version":null,"BusinessUnit":null,"Department":null,"Location":null, 232 "Coordinates":null}; 233 234 235 /** 236 * This method saves the Asset object in the Sentinel database. 237 * <p>Example: 238 * <pre> 239 * this.testasset = new Asset({"Hostname":"testname","IPv4":"10.0.0.12"}); 240 * this.testasset.save(); 241 * </pre> 242 * @return {Boolean} Result Result of the attempted save. 243 */ 244 Asset.prototype.save = function() { 245 246 /* 247 * This method will use the following translation between the JS Asset object and the Sentinel "infoblock" fields: 248 * [JS Asset attribute] -> [Infoblock tag] 249 * GUID -> EnvironmentIdentity 250 * IPv4 -> IpAddress 251 * IPv6 -> NetworkIdentity 252 * Customer -> CustomerName 253 * Hostname -> HostName 254 * MAC -> MacAddress 255 * Category -> AssetCategory 256 * Description -> AssetName 257 * Value -> AssetValue 258 * Criticality -> Criticality 259 * Vendor -> Vendor 260 * Product -> ProductName 261 * Version -> ProductVersion 262 * Owner.PrimaryEmail -> OwnerEmail 263 * Owner.FirstName -> OwnerFirstName 264 * Owner.LastName -> OwnerLastName 265 * Owner.PrimaryPhone -> OwnerPhoneNumber 266 * Owner.IdentityGuid -> Room (We are "faking" an FK over to Identity) 267 * Maintainer.PrimaryEmail -> MaintainerEmail 268 * Maintainer.FirstName -> MaintainerFirstName 269 * Maintainer.LastName -> MaintainerLastName 270 * Maintainer.PrimaryPhone -> MaintainerPhoneNumber 271 * Maintainer.IdentityGuid -> RackNumber (We are "faking" an FK over to Identity) 272 * BusinessUnit -> BusinessUnit 273 * Department -> Department 274 * Location -> AddressLine1 275 * Coordinates -> AddressLine2 276 * AssetEntryType will be hardcoded to "physical" 277 */ 278 279 // Must have one of these set 280 if (!this.IPv4 || !(/^\d+\.\d+\.\d+\.\d+$/.test(this.IPv4) )) { 281 log("Attempt to save an asset without a valid IP address"); 282 return false; 283 } 284 285 var owneremail,ownerfirst,ownerlast,ownerphone,ownerguid; 286 var maintaineremail,maintainerfirst,maintainerlast,maintainerphone,maintainerguid; 287 288 // For some strange reason, First/Last must be unique or later records will overwrite this one 289 if (this.Owner instanceof IdentityImpl && this.Owner.PrimaryEmail && this.Owner.PrimaryEmail != "") { 290 owneremail = this.Owner.PrimaryEmail; 291 ownerfirst = (!this.Owner.FirstName || this.Owner.FirstName == "null") ? this.Owner.PrimaryEmail.split("@")[0] : this.Owner.FirstName; 292 ownerlast = (!this.Owner.LastName || this.Owner.LastName == "null") ? this.Owner.PrimaryEmail.split("@")[1] : this.Owner.LastName; 293 ownerphone = this.Owner.PrimaryPhone == "null" ? "" : this.Owner.PrimaryPhone; 294 ownerguid = this.Owner.IdentityGuid; 295 } 296 297 if (this.Maintainer instanceof IdentityImpl && this.Maintainer.PrimaryEmail && this.Maintainer.PrimaryEmail != "") { 298 maintaineremail = this.Maintainer.PrimaryEmail; 299 maintainerfirst = (!this.Maintainer.FirstName || this.Maintainer.FirstName == "null") ? this.Maintainer.PrimaryEmail.split("@")[0] : this.Maintainer.FirstName; 300 maintainerlast = (!this.Maintainer.LastName || this.Maintainer.LastName == "null") ? this.Maintainer.PrimaryEmail.split("@")[1] : this.Maintainer.LastName; 301 maintainerphone = this.Maintainer.PrimaryPhone == "null" ? "" : this.Maintainer.PrimaryPhone; 302 maintainerguid = this.Maintainer.IdentityGuid; 303 } 304 305 var infoSession = new InfoBlockSession("asset", new ContextInfoSender(instance.CONFIG.scriptContext)); 306 307 if (typeof this.GUID == "undefined") { 308 //this.GUID = new Date.UTC(); 309 } 310 311 var fields = new Array("AssetEntryType","EnvironmentIdentity","IpAddress","NetworkIdentity","CustomerName", 312 "HostName","MacAddress","AssetCategory","AssetName","AssetValue","Criticality", 313 "Vendor","ProductName","ProductVersion", 314 "OwnerEmail","OwnerFirstName","OwnerLastName","OwnerPhoneNumber","Room", 315 "MaintainerEmail","MaintainerFirstName","MaintainerLastName","MaintainerPhoneNumber","RackNumber", 316 "BusinessUnit","Department","AddressLine1","AddressLine2"); 317 var values = new Array("physical",this.GUID,this.IPv4,this.IPv6,this.Customer ? this.Customer.Name : "unknown", 318 this.Hostname,this.MAC,this.Category,this.Description,this.Value,this.Criticality, 319 this.Vendor,this.Product,this.Version, 320 owneremail,ownerfirst,ownerlast,ownerphone,ownerguid, 321 maintaineremail,maintainerfirst,maintainerlast,maintainerphone,maintainerguid, 322 this.BusinessUnit,this.Department,this.Location,this.Coordinates); 323 324 var Jfields = fields.toJava(java.lang.String); 325 var Jvalues = values.toJava(java.lang.String); 326 327 infoSession.setTag(Jfields, Jvalues ); 328 329 infoSession.push(); 330 infoSession.send(); 331 infoSession.close(); 332 }; 333 334 /** 335 * Finds the asset(s) in the Sentinel database. 336 * NOT YET IMPLEMENTED. 337 * @return {Asset[]} Matching assets. 338 */ 339 Asset.prototype.find = function() { 340 return null; 341 };