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 };