Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7019 Articles
article-image-introduction-python-lists-and-dictionaries
Packt
09 Mar 2016
10 min read
Save for later

An Introduction to Python Lists and Dictionaries

Packt
09 Mar 2016
10 min read
In this article by Jessica Ingrassellino, the author of Python Projects for Kids, you will learn that Python has very efficient ways of storing data, which is one reason why it is popular among many companies that make web applications. You will learn about the two most important ways to store and retrieve data in Python—lists and dictionaries. (For more resources related to this topic, see here.) Lists Lists have many different uses when coding and many different operations can be performed on lists, thanks to Python. In this article, you will only learn some of the many uses of lists. However, if you wish to learn more about lists, the Python documentation is very detailed and available at https://docs.python.org/3/tutorial/datastructures.html?highlight=lists#more-on-lists. First, it is important to note that a list is made by assigning it a name and putting the items in the list inside of square brackets []. In your Python shell, type the three lists, one on each line: fruit = ['apple', 'banana', 'kiwi', 'dragonfruit'] years = [2012,  2013,  2014,  2015] students_in_class = [30,  22,  28,  33] The lists that you just typed have a particular kind of data inside. However, one good feature of lists is that they can mix up data types within the same list. For example, I have made this list that combines strings and integers: computer_class = ['Cynthia', 78, 42, 'Raj', 98, 24, 35, 'Kadeem', 'Rachel'] Now that we have made the lists, we can get the contents of the list in many ways. In fact, once you create a list, the computer remembers the order of the list, and the order stays constant until it is changed purposefully. The easiest way for us to see that the order of lists is maintained is to run tests on the lists that we have already made. The first item of a Python list is always counted as 0 (zero). So, for our first test, let's see if asking for the 0 item actually gives us the first item. Using our fruit list, we will type the name of the list inside of the print statement, and then add square brackets [] with the number 0: print(fruit[0]) Your output will be apple, since apple is the first fruit in the list that we created earlier. So, we have evidence that counting in Python does start with 0. Now, we can try to print the fourth item in the fruit list. You will notice that we are entering 3 in our print command. This is because the first item started at 0. Type the following code into your Python shell: print(fruit[3]) What is your outcome? Did you expect dragonfruit to be the answer? If so, good, you are learning to count items in lists. If not, remember that the first item in a list is the 0 item. With practice, you will become better at counting items in Python lists. For extra practice, work with the other lists that we made earlier, and try printing different items from the list by changing the number in the following line of code: print(list_name[item_number]) Where the code says list_name, write the name of the list that you want to use. Where the code says item_number, write the number of the item that you want to print. Remember that lists begin counting at 0. Changing the list – adding and removing information Even though lists have order, lists can be changed. Items can be added to a list, removed from a list, or changed in a list. Again, there are many ways to interact with lists. We will only discuss a few here, but you can always read the Python documentation for more information. To add an item to our fruit list, for example, we can use a method called list.append(). To use this method, type the name of the list, a dot, the method name append, and then parenthesis with the item that you would like to add contained inside. If the item is a string, remember to use single quotes. Type the following code to add an orange to the list of fruits that we have made:   fruit.append('orange') Then, print the list of fruit to see that orange has been added to the list:     print(fruit) Now, let's say that we no longer wish for the dragonfruit to appear on our list. We will use a method called list.remove(). To do this, we will type the name of our list, a dot, the method name called remove, and the name of the item that we wish to remove:     fruit.remove('dragonfruit') Then, we will print the list to see that the dragonfruit has been removed:     print(fruit) If you have more than one of the same item in the list, list.remove() will only remove the first instance of that item. The other items with the same name need to be removed separately. Loops and lists Lists and for loops work very well together. With lists, we can do something called iteration. By itself, the word iteration means to repeat a procedure over and over again. We know that the for loops repeat things for a limited and specific number of times. In this sample, we have three colors in our list. Make this list in your Python terminal: colors = ['green', 'yellow', 'red'] Using our list, we may decide that for each color in the list, we want to print the statement called I see and add each color in our list. Using the for loop with the list, we can type the print statement one time and get three statements in return. Type the following for loop into your Python shell: for color in colors:        print('I see  ' + str(color)  +  '.') Once you are done typing the print line and pressing Enter twice, your for loop will start running, and you should see the following statements printed out in your Python shell: As you can imagine, lists and the for loops are very powerful when used together. Instead of having to type the line three times with three different pieces of code, we only had to type two lines of code. We used the str() method to make sure that the sentence that we printed combined with the list items. Our for loop is helpful because those two lines of code would work if there were 20 colors in our list. Dictionaries Dictionaries are another way to organize data. At first glance, a dictionary may look just like a list. However, dictionaries have different jobs, rules, and syntax. Dictionaries have names and use curly braces to store information. For example, if we wanted to make a dictionary called sports, we would then put the dictionary entries inside of curly braces. Here is a simple example: numbers = {'one': 1, 'two': 2, 'three': 3} Key/value pairs in dictionaries A dictionary stores information with things called keys and values. In a dictionary of items, for example, we may have keys that tell us the names of each item and values that tell us how many of each item we have in our inventory. Once we store these items in our dictionary, we can add or remove new items (keys), add new amounts (values), or change the amounts of existing items. Here is an example of a dictionary that could hold some information for a game. Let’s suppose that the hero in our game has some items needed to survive. Here is a dictionary of our hero's items: items = {'arrows' : 200, 'rocks' : 25, 'food' : 15, 'lives' : 2} Unlike lists, a dictionary uses keys and values to find information. So, this dictionary has the keys called arrows, rocks, food, and lives. Each of the numbers tells us the amount of items that our hero has. Dictionaries have different characteristics than lists do. So, we can look up certain items in our dictionary using the print function: print(items['arrows']) The result of this print command will print 200, as this is the number of arrows our hero has in his inventory: Changing the dictionary – adding and removing information Python offers us ways not only to make a dictionary but to also add and remove things from our dictionaries. For example, let's say that in our game, we allow the player to discover a fireball later in the game. To add the item to the dictionary, we will use what is called the subscript method to add a new key and a new value to our dictionary. This means that we will use the name of the dictionary and square brackets to write the name of the item that we wish to add, and finally, we will set the value to how many items we want to put into our dictionary:   items['fireball'] = 10 If we print the entire dictionary of items, you will see that fireball has been added:   print(items)   items = {'arrows' : 200, 'rocks' : 25, 'food' : 15, 'lives' : 2, 'fireball' : 10} We can also change the number of items in our dictionary using the dict.update() method. This method uses the name of the dictionary and the word update. Then, in parentheses (), we use curly braces {} to type the name of the item that we wish to update—a colon (:), and the new number of items we want in the dictionary. Try this in your Python shell:   items.update({'rocks':10})   print(items) You will notice that if you have done print(items), then you will now have 10 rocks instead of 25. We have successfully updated our number of items. To remove something from a dictionary, one must reference the key or the name of the item and delete the item. By doing so, the value that goes with the item will also be removed. In Python, this means using del along with the name of the dictionary and the name of the item you wish to remove. Using the items list as our example, let's remove lives, and then use a print statement to test and see if the lives key was removed:   del items['lives']   print(items) The items list will now look as follows: With dictionaries, information is stored and retrieved differently than with lists, but we can still perform the same operation of adding and removing information as well as making changes to information. Summary Lists and dictionaries are two different ways to store and retrieve information in Python. Although, the sample data that we saw in this article was small, Python can handle large sets of data and process them at high speeds. Learning to use lists and dictionaries will allow you to solve complicated programming problems in many realms, including gaming, web app development, and data analysis. Resources for Article: Further resources on this subject: Exception Handling in MySQL for Python [article] Configuring and securing PYTHON LDAP Applications Part 1 [article] Web scraping with Python (Part 2) [article]
Read more
  • 0
  • 0
  • 4833

article-image-python-data-structures
Packt
09 Mar 2016
23 min read
Save for later

Python Data Structures

Packt
09 Mar 2016
23 min read
In this article written by Dusty Phillips, author of the book Python 3 Object-oriented Programming - Second Edition we'll be discussing the object-oriented features of data structures, when they should be used instead of a regular class, and when they should not be used. In particular, we'll be covering: Tuples and named tuples Dictionaries (For more resources related to this topic, see here.) Empty objects Let's start with the most basic Python built-in, one that we've seen many times already, the one that we've extended in every class we have created: the object. Technically, we can instantiate an object without writing a subclass: >>> o = object() >>> o.x = 5 Traceback (most recent call last):   File "<stdin>", line 1, in <module> AttributeError: 'object' object has no attribute 'x' Unfortunately, as you can see, it's not possible to set any attributes on an object that was instantiated directly. This isn't because the Python developers wanted to force us to write our own classes, or anything so sinister. They did this to save memory; a lot of memory. When Python allows an object to have arbitrary attributes, it takes a certain amount of system memory to keep track of what attributes each object has, for storing both the attribute name and its value. Even if no attributes are stored, memory is allocated for potential new attributes. Given the dozens, hundreds, or thousands of objects (every class extends object) in a typical Python program; this small amount of memory would quickly become a large amount of memory. So, Python disables arbitrary properties on object, and several other built-ins, by default. It is possible to restrict arbitrary properties on our own classes using slots. You now have a search term if you are looking for more information. In normal use, there isn't much benefit to using slots, but if you're writing an object that will be duplicated thousands of times throughout the system, they can help save memory, just as they do for object. It is, however, trivial to create an empty object class of our own; we saw it in our earliest example: class MyObject:     pass And, as we've already seen, it's possible to set attributes on such classes: >>> m = MyObject() >>> m.x = "hello" >>> m.x 'hello' If we wanted to group properties together, we could store them in an empty object like this. But we are usually better off using other built-ins designed for storing data. It has been stressed that classes and objects should only be used when you want to specify both data and behaviors. The main reason to write an empty class is to quickly block something out, knowing we'll come back later to add behavior. It is much easier to adapt behaviors to a class than it is to replace a data structure with an object and change all references to it. Therefore, it is important to decide from the outset if the data is just data, or if it is an object in disguise. Once that design decision is made, the rest of the design naturally falls into place. Tuples and named tuples Tuples are objects that can store a specific number of other objects in order. They are immutable, so we can't add, remove, or replace objects on the fly. This may seem like a massive restriction, but the truth is, if you need to modify a tuple, you're using the wrong data type (usually a list would be more suitable). The primary benefit of tuples' immutability is that we can use them as keys in dictionaries, and in other locations where an object requires a hash value. Tuples are used to store data; behavior cannot be stored in a tuple. If we require behavior to manipulate a tuple, we have to pass the tuple into a function (or method on another object) that performs the action. Tuples should generally store values that are somehow different from each other. For example, we would not put three stock symbols in a tuple, but we might create a tuple of stock symbol, current price, high, and low for the day. The primary purpose of a tuple is to aggregate different pieces of data together into one container. Thus, a tuple can be the easiest tool to replace the "object with no data" idiom. We can create a tuple by separating the values with a comma. Usually, tuples are wrapped in parentheses to make them easy to read and to separate them from other parts of an expression, but this is not always mandatory. The following two assignments are identical (they record a stock, the current price, the high, and the low for a rather profitable company): >>> stock = "FB", 75.00, 75.03, 74.90 >>> stock2 = ("FB", 75.00, 75.03, 74.90) If we're grouping a tuple inside of some other object, such as a function call, list comprehension, or generator, the parentheses are required. Otherwise, it would be impossible for the interpreter to know whether it is a tuple or the next function parameter. For example, the following function accepts a tuple and a date, and returns a tuple of the date and the middle value between the stock's high and low value: import datetime def middle(stock, date):     symbol, current, high, low = stock     return (((high + low) / 2), date)   mid_value, date = middle(("FB", 75.00, 75.03, 74.90),         datetime.date(2014, 10, 31)) The tuple is created directly inside the function call by separating the values with commas and enclosing the entire tuple in parenthesis. This tuple is then followed by a comma to separate it from the second argument. This example also illustrates tuple unpacking. The first line inside the function unpacks the stock parameter into four different variables. The tuple has to be exactly the same length as the number of variables, or it will raise an exception. We can also see an example of tuple unpacking on the last line, where the tuple returned inside the function is unpacked into two values, mid_value and date. Granted, this is a strange thing to do, since we supplied the date to the function in the first place, but it gave us a chance to see unpacking at work. Unpacking is a very useful feature in Python. We can group variables together to make storing and passing them around simpler, but the moment we need to access all of them, we can unpack them into separate variables. Of course, sometimes we only need access to one of the variables in the tuple. We can use the same syntax that we use for other sequence types (lists and strings, for example) to access an individual value: >>> stock = "FB", 75.00, 75.03, 74.90 >>> high = stock[2] >>> high 75.03 We can even use slice notation to extract larger pieces of tuples: >>> stock[1:3] (75.00, 75.03) These examples, while illustrating how flexible tuples can be, also demonstrate one of their major disadvantages: readability. How does someone reading this code know what is in the second position of a specific tuple? They can guess, from the name of the variable we assigned it to, that it is high of some sort, but if we had just accessed the tuple value in a calculation without assigning it, there would be no such indication. They would have to paw through the code to find where the tuple was declared before they could discover what it does. Accessing tuple members directly is fine in some circumstances, but don't make a habit of it. Such so-called "magic numbers" (numbers that seem to come out of thin air with no apparent meaning within the code) are the source of many coding errors and lead to hours of frustrated debugging. Try to use tuples only when you know that all the values are going to be useful at once and it's normally going to be unpacked when it is accessed. If you have to access a member directly or using a slice and the purpose of that value is not immediately obvious, at least include a comment explaining where it came from. Named tuples So, what do we do when we want to group values together, but know we're frequently going to need to access them individually? Well, we could use an empty object, as discussed in the previous section (but that is rarely useful unless we anticipate adding behavior later), or we could use a dictionary (most useful if we don't know exactly how many or which specific data will be stored), as we'll cover in the next section. If, however, we do not need to add behavior to the object, and we know in advance what attributes we need to store, we can use a named tuple. Named tuples are tuples with attitude. They are a great way to group read-only data together. Constructing a named tuple takes a bit more work than a normal tuple. First, we have to import namedtuple, as it is not in the namespace by default. Then, we describe the named tuple by giving it a name and outlining its attributes. This returns a class-like object that we can instantiate with the required values as many times as we want: from collections import namedtuple Stock = namedtuple("Stock", "symbol current high low") stock = Stock("FB", 75.00, high=75.03, low=74.90) The namedtuple constructor accepts two arguments. The first is an identifier for the named tuple. The second is a string of space-separated attributes that the named tuple can have. The first attribute should be listed, followed by a space (or comma if you prefer), then the second attribute, then another space, and so on. The result is an object that can be called just like a normal class to instantiate other objects. The constructor must have exactly the right number of arguments that can be passed in as arguments or keyword arguments. As with normal objects, we can create as many instances of this "class" as we like, with different values for each. The resulting namedtuple can then be packed, unpacked, and otherwise treated like a normal tuple, but we can also access individual attributes on it as if it were an object: >>> stock.high 75.03 >>> symbol, current, high, low = stock >>> current 75.00 Remember that creating named tuples is a two-step process. First, use collections.namedtuple to create a class, and then construct instances of that class. Named tuples are perfect for many "data only" representations, but they are not ideal for all situations. Like tuples and strings, named tuples are immutable, so we cannot modify an attribute once it has been set. For example, the current value of my company's stock has gone down since we started this discussion, but we can't set the new value: >>> stock.current = 74.98 Traceback (most recent call last):   File "<stdin>", line 1, in <module> AttributeError: can't set attribute If we need to be able to change stored data, a dictionary may be what we need instead. Dictionaries Dictionaries are incredibly useful containers that allow us to map objects directly to other objects. An empty object with attributes to it is a sort of dictionary; the names of the properties map to the property values. This is actually closer to the truth than it sounds; internally, objects normally represent attributes as a dictionary, where the values are properties or methods on the objects (see the __dict__ attribute if you don't believe me). Even the attributes on a module are stored, internally, in a dictionary. Dictionaries are extremely efficient at looking up a value, given a specific key object that maps to that value. They should always be used when you want to find one object based on some other object. The object that is being stored is called the value; the object that is being used as an index is called the key. We've already seen dictionary syntax in some of our previous examples. Dictionaries can be created either using the dict() constructor or using the {} syntax shortcut. In practice, the latter format is almost always used. We can prepopulate a dictionary by separating the keys from the values using a colon, and separating the key value pairs using a comma. For example, in a stock application, we would most often want to look up prices by the stock symbol. We can create a dictionary that uses stock symbols as keys, and tuples of current, high, and low as values like this: stocks = {"GOOG": (613.30, 625.86, 610.50),           "MSFT": (30.25, 30.70, 30.19)} As we've seen in previous examples, we can then look up values in the dictionary by requesting a key inside square brackets. If the key is not in the dictionary, it will raise an exception: >>> stocks["GOOG"] (613.3, 625.86, 610.5) >>> stocks["RIM"] Traceback (most recent call last):   File "<stdin>", line 1, in <module> KeyError: 'RIM' We can, of course, catch the KeyError and handle it. But we have other options. Remember, dictionaries are objects, even if their primary purpose is to hold other objects. As such, they have several behaviors associated with them. One of the most useful of these methods is the get method; it accepts a key as the first parameter and an optional default value if the key doesn't exist: >>> print(stocks.get("RIM")) None >>> stocks.get("RIM", "NOT FOUND") 'NOT FOUND' For even more control, we can use the setdefault method. If the key is in the dictionary, this method behaves just like get; it returns the value for that key. Otherwise, if the key is not in the dictionary, it will not only return the default value we supply in the method call (just like get does), it will also set the key to that same value. Another way to think of it is that setdefault sets a value in the dictionary only if that value has not previously been set. Then it returns the value in the dictionary, either the one that was already there, or the newly provided default value. >>> stocks.setdefault("GOOG", "INVALID") (613.3, 625.86, 610.5) >>> stocks.setdefault("BBRY", (10.50, 10.62, 10.39)) (10.50, 10.62, 10.39) >>> stocks["BBRY"] (10.50, 10.62, 10.39) The GOOG stock was already in the dictionary, so when we tried to setdefault it to an invalid value, it just returned the value already in the dictionary. BBRY was not in the dictionary, so setdefault returned the default value and set the new value in the dictionary for us. We then check that the new stock is, indeed, in the dictionary. Three other very useful dictionary methods are keys(), values(), and items(). The first two return an iterator over all the keys and all the values in the dictionary. We can use these like lists or in for loops if we want to process all the keys or values. The items() method is probably the most useful; it returns an iterator over tuples of (key, value) pairs for every item in the dictionary. This works great with tuple unpacking in a for loop to loop over associated keys and values. This example does just that to print each stock in the dictionary with its current value: >>> for stock, values in stocks.items(): ...     print("{} last value is {}".format(stock, values[0])) ... GOOG last value is 613.3 BBRY last value is 10.50 MSFT last value is 30.25 Each key/value tuple is unpacked into two variables named stock and values (we could use any variable names we wanted, but these both seem appropriate) and then printed in a formatted string. Notice that the stocks do not show up in the same order in which they were inserted. Dictionaries, due to the efficient algorithm (known as hashing) that is used to make key lookup so fast, are inherently unsorted. So, there are numerous ways to retrieve data from a dictionary once it has been instantiated; we can use square brackets as index syntax, the get method, the setdefault method, or iterate over the items method, among others. Finally, as you likely already know, we can set a value in a dictionary using the same indexing syntax we use to retrieve a value: >>> stocks["GOOG"] = (597.63, 610.00, 596.28) >>> stocks['GOOG'] (597.63, 610.0, 596.28) Google's price is lower today, so I've updated the tuple value in the dictionary. We can use this index syntax to set a value for any key, regardless of whether the key is in the dictionary. If it is in the dictionary, the old value will be replaced with the new one; otherwise, a new key/value pair will be created. We've been using strings as dictionary keys, so far, but we aren't limited to string keys. It is common to use strings as keys, especially when we're storing data in a dictionary to gather it together (instead of using an object with named properties). But we can also use tuples, numbers, or even objects we've defined ourselves as dictionary keys. We can even use different types of keys in a single dictionary: random_keys = {} random_keys["astring"] = "somestring" random_keys[5] = "aninteger" random_keys[25.2] = "floats work too" random_keys[("abc", 123)] = "so do tuples"   class AnObject:     def __init__(self, avalue):         self.avalue = avalue   my_object = AnObject(14) random_keys[my_object] = "We can even store objects" my_object.avalue = 12 try:     random_keys[[1,2,3]] = "we can't store lists though" except:     print("unable to store listn")   for key, value in random_keys.items():     print("{} has value {}".format(key, value)) This code shows several different types of keys we can supply to a dictionary. It also shows one type of object that cannot be used. We've already used lists extensively, and we'll be seeing many more details of them in the next section. Because lists can change at any time (by adding or removing items, for example), they cannot hash to a specific value. Objects that are hashable basically have a defined algorithm that converts the object into a unique integer value for rapid lookup. This hash is what is actually used to look up values in a dictionary. For example, strings map to integers based on the characters in the string, while tuples combine hashes of the items inside the tuple. Any two objects that are somehow considered equal (like strings with the same characters or tuples with the same values) should have the same hash value, and the hash value for an object should never ever change. Lists, however, can have their contents changed, which would change their hash value (two lists should only be equal if their contents are the same). Because of this, they can't be used as dictionary keys. For the same reason, dictionaries cannot be used as keys into other dictionaries. In contrast, there are no limits on the types of objects that can be used as dictionary values. We can use a string key that maps to a list value, for example, or we can have a nested dictionary as a value in another dictionary. Dictionary use cases Dictionaries are extremely versatile and have numerous uses. There are two major ways that dictionaries can be used. The first is dictionaries where all the keys represent different instances of similar objects; for example, our stock dictionary. This is an indexing system. We use the stock symbol as an index to the values. The values could even have been complicated self-defined objects that made buy and sell decisions or set a stop-loss, rather than our simple tuples. The second design is dictionaries where each key represents some aspect of a single structure; in this case, we'd probably use a separate dictionary for each object, and they'd all have similar (though often not identical) sets of keys. This latter situation can often also be solved with named tuples. These should typically be used when we know exactly what attributes the data must store, and we know that all pieces of the data must be supplied at once (when the item is constructed). But if we need to create or change dictionary keys over time or we don't know exactly what the keys might be, a dictionary is more suitable. Using defaultdict We've seen how to use setdefault to set a default value if a key doesn't exist, but this can get a bit monotonous if we need to set a default value every time we look up a value. For example, if we're writing code that counts the number of times a letter occurs in a given sentence, we could do this: def letter_frequency(sentence):     frequencies = {}     for letter in sentence:         frequency = frequencies.setdefault(letter, 0)         frequencies[letter] = frequency + 1     return frequencies Every time we access the dictionary, we need to check that it has a value already, and if not, set it to zero. When something like this needs to be done every time an empty key is requested, we can use a different version of the dictionary, called defaultdict: from collections import defaultdict def letter_frequency(sentence):     frequencies = defaultdict(int)     for letter in sentence:         frequencies[letter] += 1     return frequencies This code looks like it couldn't possibly work. The defaultdict accepts a function in its constructor. Whenever a key is accessed that is not already in the dictionary, it calls that function, with no parameters, to create a default value. In this case, the function it calls is int, which is the constructor for an integer object. Normally, integers are created simply by typing an integer number into our code, and if we do create one using the int constructor, we pass it the item we want to create (for example, to convert a string of digits into an integer). But if we call int without any arguments, it returns, conveniently, the number zero. In this code, if the letter doesn't exist in the defaultdict, the number zero is returned when we access it. Then we add one to this number to indicate we've found an instance of that letter, and the next time we find one, that number will be returned and we can increment the value again. The defaultdict is useful for creating dictionaries of containers. If we want to create a dictionary of stock prices for the past 30 days, we could use a stock symbol as the key and store the prices in list; the first time we access the stock price, we would want it to create an empty list. Simply pass list into the defaultdict, and it will be called every time an empty key is accessed. We can do similar things with sets or even empty dictionaries if we want to associate one with a key. Of course, we can also write our own functions and pass them into the defaultdict. Suppose we want to create a defaultdict where each new element contains a tuple of the number of items inserted into the dictionary at that time and an empty list to hold other things. Nobody knows why we would want to create such an object, but let's have a look: from collections import defaultdict num_items = 0 def tuple_counter():     global num_items     num_items += 1     return (num_items, [])   d = defaultdict(tuple_counter) When we run this code, we can access empty keys and insert into the list all in one statement: >>> d = defaultdict(tuple_counter) >>> d['a'][1].append("hello") >>> d['b'][1].append('world') >>> d defaultdict(<function tuple_counter at 0x82f2c6c>, {'a': (1, ['hello']), 'b': (2, ['world'])}) When we print dict at the end, we see that the counter really was working. This example, while succinctly demonstrating how to create our own function for defaultdict, is not actually very good code; using a global variable means that if we created four different defaultdict segments that each used tuple_counter, it would count the number of entries in all dictionaries, rather than having a different count for each one. It would be better to create a class and pass a method on that class to defaultdict. Counter You'd think that you couldn't get much simpler than defaultdict(int), but the "I want to count specific instances in an iterable" use case is common enough that the Python developers created a specific class for it. The previous code that counts characters in a string can easily be calculated in a single line: from collections import Counter def letter_frequency(sentence):     return Counter(sentence) The Counter object behaves like a beefed up dictionary where the keys are the items being counted and the values are the number of such items. One of the most useful functions is the most_common() method. It returns a list of (key, count) tuples ordered by the count. You can optionally pass an integer argument into most_common() to request only the top most common elements. For example, you could write a simple polling application as follows: from collections import Counter   responses = [     "vanilla",     "chocolate",     "vanilla",     "vanilla",     "caramel",     "strawberry",     "vanilla" ]   print(     "The children voted for {} ice cream".format(         Counter(responses).most_common(1)[0][0]     ) ) Presumably, you'd get the responses from a database or by using a complicated vision algorithm to count the kids who raised their hands. Here, we hardcode it so that we can test the most_common method. It returns a list that has only one element (because we requested one element in the parameter). This element stores the name of the top choice at position zero, hence the double [0][0] at the end of the call. I think they look like a surprised face, don't you? Your computer is probably amazed it can count data so easily. It's ancestor, Hollerith's Tabulating Machine for the 1890 US census, must be so jealous! Summary We've covered several built-in data structures and attempted to understand how to choose one for specific applications. Sometimes, the best thing we can do is create a new class of objects, but often, one of the built-ins provides exactly what we need. When it doesn't, we can always use inheritance or composition to adapt them to our use cases. We can even override special methods to completely change the behavior of built-in syntaxes. Be sure to pick up the full title, Python 3 Object-oriented Programming - Second Edition, to continue your learning in the world of OOP Python. If you want to go above and beyond then there’s no better way than building on what you’ve discovered with Mastering Object-oriented Python and Learning Object-Oriented Programming too! Resources for Article:   Further resources on this subject: Python LDAP applications - extra LDAP operations and the LDAP URL library [article] Exception Handling in MySQL for Python [article] Data Transactions Made Easy with MySQL and Python [article]
Read more
  • 0
  • 0
  • 3247

Packt
08 Mar 2016
17 min read
Save for later

Magento 2 – the New E-commerce Era

Packt
08 Mar 2016
17 min read
In this article by Ray Bogman and Vladimir Kerkhoff, the authors of the book, Magento 2 Cookbook, we will cover the basic tasks related to creating a catalog and products in Magento 2. You will learn the following recipes: Creating a root catalog Creating subcategories Managing an attribute set (For more resources related to this topic, see here.) Introduction This article explains how to set up a vanilla Magento 2 store. If Magento 2 is totally new for you, then lots of new basic whereabouts are pointed out. If you are currently working with Magento 1, then not a lot has changed since. The new backend of Magento 2 is the biggest improvement of them all. The design is built responsively and has a great user experience. Compared to Magento 1, this is a great improvement. The menu is located vertically on the left of the screen and works great on desktop and mobile environments: In this article, we will see how to set up a website with multiple domains using different catalogs. Depending on the website, store, and store view setup, we can create different subcategories, URLs, and product per domain name. There are a number of different ways customers can browse your store, but one of the most effective one is layered navigation. Layered navigation is located in your catalog and holds product features to sort or filter. Every website benefits from great Search Engine Optimization (SEO). You will learn how to define catalog URLs per catalog. Throughout this article, we will cover the basics on how to set up a multidomain setup. Additional tasks required to complete a production-like setup are out of the scope of this article. Creating a root catalog The first thing that we need to start with when setting up a vanilla Magento 2 website is defining our website, store, and store view structure. So what is the difference between website, store, and store view, and why is it important: A website is the top-level container and most important of the three. It is the parent level of the entire store and used, for example, to define domain names, different shipping methods, payment options, customers, orders, and so on. Stores can be used to define, for example, different store views with the same information. A store is always connected to a root catalog that holds all the categories and subcategories. One website can manage multiple stores, and every store has a different root catalog. When using multiple stores, it is not possible to share one basket. The main reason for this has to do with the configuration setup where shipping, catalog, customer, inventory, taxes, and payment settings are not sharable between different sites. Store views is the lowest level and mostly used to handle different localizations. Every store view can be set with a different language. Besides using store views just for localizations, it can also be used for Business to Business (B2B), hidden private sales pages (with noindex and nofollow), and so on. The option where we use the base link URL, for example, (yourdomain.com/myhiddenpage) is easy to set up. The website, store, and store view structure is shown in the following image: Getting ready For this recipe, we will use a Droplet created at DigitalOcean, https://www.digitalocean.com/. We will be using NGINX, PHP-FPM, and a Composer-based setup including Magento 2 preinstalled. No other prerequisites are required. How to do it... For the purpose of this recipe, let's assume that we need to create a multi-website setup including three domains (yourdomain.com, yourdomain.de, and yourdomain.fr) and separate root catalogs. The following steps will guide you through this: First, we need to update our NGINX. We need to configure the additional domains before we can connect them to Magento. Make sure that all domain names are connected to your server and DNS is configured correctly. Go to /etc/nginx/conf.d, open the default.conf file, and include the following content at the top of your file: map $http_host $magecode { hostnames; default base; yourdomain.de de; yourdomain.fr fr; } Your configuration should look like this now: map $http_host $magecode { hostnames; default base; yourdomain.de de; yourdomain.fr fr; } upstream fastcgi_backend { server 127.0.0.1:9000; } server { listen 80; listen 443 ssl http2; server_name yourdomain.com; set $MAGE_ROOT /var/www/html; set $MAGE_MODE developer; ssl_certificate /etc/ssl/yourdomain-com.cert; ssl_certificate_key /etc/ssl/yourdomain-com.key; include /var/www/html/nginx.conf.sample; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; location ~ /\.ht { deny all; } } Now let's go to the Magento 2 configuration file in /var/www/html/ and open the nginx.conf.sample file. Go to the bottom and look for the following: location ~ (index|get|static|report|404|503)\.php$ Now we add the following lines to the file under fastcgi_pass   fastcgi_backend;: fastcgi_param MAGE_RUN_TYPE website; fastcgi_param MAGE_RUN_CODE $magecode; Your configuration should look like this now (this is only a small section of the bottom section): location ~ (index|get|static|report|404|503)\.php$ { try_files $uri =404; fastcgi_pass fastcgi_backend; fastcgi_param MAGE_RUN_TYPE website; fastcgi_param MAGE_RUN_CODE $magecode; fastcgi_param PHP_FLAG "session.auto_start=off \n suhosin.session.cryptua=off"; fastcgi_param PHP_VALUE "memory_limit=256M \n max_execution_time=600"; fastcgi_read_timeout 600s; fastcgi_connect_timeout 600s; fastcgi_param MAGE_MODE $MAGE_MODE; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } The current setup is using the MAGE_RUN_TYPE website variable. You may change website to store depending on your setup preferences. When changing the variable, you need your default.conf mapping codes as well. Now, all you have to do is restart NGINX and PHP-FPM to use your new settings. Run the following command: service nginx restart && service php-fpm restart Before we continue we need to check whether our web server is serving the correct codes. Run the following command in the Magento 2 web directory: var/www/html/pub echo "<?php header("Content-type: text/plain"); print_r($_SERVER); ?>" > magecode.php Don't forget to update your nginx.conf.sample file with the new magecode code. It's located at the bottom of your file and should look like this: location ~ (index|get|static|report|404|503|magecode)\.php$ { Restart NGINX and open the file in your browser. The output should look as follows. As you can see, the created MAGE_RUN variables are available. Congratulations, you just finished configuring NGINX including additional domains. Now let's continue connecting them in Magento 2. Now log in to the backend and navigate to Stores | All Stores. By default, Magento 2 has one Website, Store, and Store View setup. Now click on Create Website and commit the following details: Name My German Website Code de Next, click on Create Store and commit the following details: Web site My German Website Name My German Website Root Category Default Category (we will change this later)  Next, click on Create Store View and commit the following details: Store My German Website Name German Code de Status Enabled  Continue the same step for the French domain. Make sure that the Code in Website and Store View is fr. The next important step is connecting the websites with the domain name. Navigate to Stores | Configuration | Web | Base URLs. Change the Store View scope at the top to My German Website. You will be prompted when switching; press ok to continue. Now, unset the checkbox called Use Default from Base URL and Base Link URL and commit your domain name. Save and continue the same procedure for the other website. The output should look like this: Save your entire configuration and clear your cache. Now go to Products | Categories and click on Add Root Category with the following data: Name Root German Is Active Yes Page Title My German Website Continue the same step for the French domain. You may add additional information here but it is not needed. Changing the current Root Category called Default Category to Root English is also optional but advised. Save your configuration, go to Stores | All Stores, and change all of the stores to the appropriate Root Catalog that we just created. Every Root Category should now have a dedicated Root Catalog. Congratulations, you just finished configuring Magento 2 including additional domains and dedicated Root Categories. Now let's open a browser and surf to your created domain names: yourdomain.com, yourdomain.de, and yourdomain.fr. How it works… Let's recap and find out what we did throughout this recipe. In steps 1 through 11, we created a multistore setup for .com, .de, and .fr domains using a separate Root Catalog. In steps 1 through 4, we configured the domain mapping in the NGINX default.conf file. Then, we added the fastcgi_param MAGE_RUN code to the nginx.conf.sample file, which will manage what website or store view to request within Magento. In step 6, we used an easy test method to check whether all domains run the correct MAGE_RUN code. In steps 7 through 9, we configured the website, store, and store view name and code for the given domain names. In step 10, we created additional Root Catalogs for the remaining German and French stores. They are then connected to the previously created store configuration. All stores have their own Root Catalog now. There's more… Are you able to buy additional domain names but like to try setting up a multistore? Here are some tips to create one. Depending on whether you are using Windows, Mac OS, or Linux, the following options apply: Windows: Go to C:\Windows\System32\drivers\etc, open up the hosts file as an administrator, and add the following: (Change the IP and domain name accordingly.) 123.456.789.0 yourdomain.de 123.456.789.0 yourdomain.fr 123.456.789.0 www.yourdomain.de 123.456.789.0 www.yourdomain.fr Save the file and click on the Start button; then search for cmd.exe and commit the following: ipconfig /flushdns Mac OS: Go to the /etc/ directory, open the hosts file as a super user, and add the following: (Change the IP and domain name accordingly.) 123.456.789.0 yourdomain.de 123.456.789.0 yourdomain.fr 123.456.789.0 www.yourdomain.de 123.456.789.0 www.yourdomain.fr Save the file and run the following command on the shell: dscacheutil -flushcache Depending on your Mac version, check out the different commands here: http://www.hongkiat.com/blog/how-to-clear-flush-dns-cache-in-os-x-yosemite/ Linux: Go to the /etc/ directory, open the hosts file as a root user, and add the following: (Change the IP and domain name accordingly.) 123.456.789.0 yourdomain.de 123.456.789.0 yourdomain.fr 123.456.789.0 www.yourdomain.de 123.456.789.0 www.yourdomain.fr Save the file and run the following command on the shell: service nscd restart Depending on your Linux version, check out the different commands here: http://www.cyberciti.biz/faq/rhel-debian-ubuntu-flush-clear-dns-cache/ Open your browser and surf to the custom-made domains. These domains work only on your PC. You can copy these IP and domain names on as many PCs as you prefer. This method also works great when you are developing or testing and your production domain is not available on your development environment. Creating subcategories After creating the foundation of the website, we need to set up a catalog structure. Setting up a catalog structure is not difficult, but needs to be thought out well. Some websites have an easy setup using two levels, while others sometimes use five or more subcategories. Always keep in mind the user experience; your customer needs to crawl the pages easily. Keep it simple! Getting ready For this recipe, we will use a Droplet created at DigitalOcean, https://www.digitalocean.com/. We will be using NGINX, PHP-FPM, and a Composer-based setup including Magento 2 preinstalled. No other prerequisites are required. How to do it... For the purpose of this recipe, let's assume that we need to set up a catalog including subcategories. The following steps will guide you through this: First, log in to the backend of Magento 2 and go to Products | Categories. As we have already created Root Catalogs, we start with using the Root English catalog first. Click on the Root English catalog on the left and then select the Add Subcategory button above the menu. Now commit the following and repeat all steps again for the other Root Catalogs: Name Shoes (Schuhe) (Chaussures) Is Active Yes Page Title Shoes (Schuhe) (Chaussures) Name Clothes (Kleider) (Vêtements) Is Active Yes Page Title Clothes (Kleider) (Vêtements) As we have created the first level of our catalog, we can continue with the second level. Now click on the first level that you need to extend with a subcategory and select the Add Subcategory button. Now commit the following and repeat all steps again for the other Root Catalogs: Name Men (Männer) (Hommes) Is Active Yes Page Title Men (Männer) (Hommes) Name Women (Frau) (Femmes) Is Active Yes Page Title Women (Frau) (Femmes) Congratulations, you just finished configuring subcategories in Magento 2. Now let's open a browser and surf to your created domain names: yourdomain.com, yourdomain.de, and yourdomain.fr. Your categories should now look as follows: How it works… Let's recap and find out what we did throughout this recipe. In steps 1 through 4, we created subcategories for the English, German, and French stores. In this recipe, we created a dedicated Root Catalog for every website. This way, every store can be configured using their own tax and shipping rules. There's more… In our example, we only submitted Name, Is Active, and Page Title. You may continue to commit the Description, Image, Meta Keywords, and Meta Description fields. By default, the URL key is the same as the Name field; you can change this depending on your SEO needs. Every category or subcategory has a default page layout defined by the theme. You may need to override this. Go to the Custom Design tab and click the drop-down menu of Page Layout. We can choose from the following options: 1 column, 2 columns with left bar, 2 columns with right bar, 3 columns, or Empty. Managing an attribute set Every product has a unique DNA; some products such as shoes could have different colors, brands, and sizes, while a snowboard could have weight, length, torsion, manufacture, and style. Setting up a website with all the attributes does not make sense. Depending on the products that you sell, you should create attributes that apply per website. When creating products for your website, attributes are the key elements and need to be thought through. What and how many attributes do I need? How many values does one need? All types of questions that could have a great impact on your website and, not to forget, the performance of it. Creating an attribute such as color and having 100 K of different key values stored is not improving your overall speed and user experience. Always think things through. After creating the attributes, we combine them in attribute sets that can be picked when starting to create a product. Some attributes can be used more than once, while others are unique to one product of an attribute set. Getting ready For this recipe, we will use a Droplet created at DigitalOcean, https://www.digitalocean.com/. We will be using NGINX, PHP-FPM, and a Composer-based setup including Magento 2 preinstalled. No other prerequisites are required. How to do it... For the purpose of this recipe, let's assume that we need to create product attributes and sets. The following steps will guide you through this: First, log in to the backend of Magento 2 and go to Stores | Products. As we are using a vanilla setup, only system attributes and one attribute set is installed. Now click on Add New Attribute and commit the following data in the Properties tab: Attribute Properties Default label shoe_size Catalog Input Type for Store Owners Dropdown Values Required No Manage Options (values of your attribute) English Admin French German 4 4 35 35 4.5 4.5 35 35 5 5 35-36 35-36 5.5 5.5 36 36 6 6 36-37 36-37 6.5 6.5 37 37 7 7 37-38 37-38 7.5 7.5 38 38 8 8 38-39 38-39 8.5 8.5 39 39 Advanced Attribute Properties Scope Global Unique Value No Add to Column Options Yes Use in Filer Options Yes As we have already set up a multi-website that sells shoes and clothes, we stick with this. The attributes that we need to sell shoes are: shoe_size, shoe_type, width, color, gender, and occasion. Continue with the rest of the chart accordingly (http://www.shoesizingcharts.com). Click on Save and Continue Edit now and continue on the Manage Labels tab with the following information: Manage Titles (Size, Color, etc.) English French German Size Taille Größe Click on Save and Continue Edit now and continue on the Storefront Properties tab with the following information: Storefront Properties Use in Search No Comparable in Storefront No Use in Layered Navigation Filterable (with result) Use in Search Result Layered Navigation No Position 0 Use for Promo Rule Conditions No Allow HTML Tags on Storefront Yes Visible on Catalog Pages on Storefront Yes Used in Product Listing No Used for Sorting in Product Listing No Click on Save Attribute now and clear the cache. Depending on whether you have set up the index management accordingly through the Magento 2 cronjob, it will automatically update the newly created attribute. The additional shoe_type, width, color, gender, and occasion attributes configuration can be downloaded at https://github.com/mage2cookbook/chapter4. After creating all of the attributes, we combine them in an attribute set called Shoes. Go to Stores | Attribute Set, click on Add Attribute Set, and commit the following data: Edit Attribute Set Name Name Shoes Based On Default Now click on the Add New button in the Groups section and commit the group name called Shoes. The newly created group is now located at the bottom of the list. You may need to scroll down before you see it. It is possible to drag and drop the group higher up in the list. Now drag and drop the created attributes, shoe_size, shoe_type, width, color, gender, and occasion to the group and save the configuration. The notice of the cron job is automatically updated depending on your settings. Congratulations, you just finished creating attributes and attribute sets in Magento 2. This can be seen in the following screenshot: How it works… Let's recap and find out what we did throughout this recipe. In steps 1 through 10, we created attributes that will be used in an attribute set. The attributes and sets are the fundamentals for every website. In steps 1 through 5, we created multiple attributes to define all details about the shoes and clothes that we would like to sell. Some attributes are later used as configurable values on the frontend while others only indicate the gender or occasion. In steps 6 through 9, we connected the attributes to the related attribute set so that when creating a product, all correct elements are available. There's more… After creating the attribute set for Shoes, we continue to create an attribute set for Clothes. Use the following attributes to create the set: color, occasion, apparel_type, sleeve_length, fit, size, length, and gender. Follow the same steps as we did before to create a new attribute set. You may reuse the attributes, color, occasion, and gender. All detailed attributes can be found at https://github.com/mage2cookbook/chapter4#clothes-set. The following is the screenshot of the Clothes attribute set: Summary In this article, you learned how to create a Root Catalog, subcategories, and manage attribute sets. For more information on Magento 2, Refer the following books by Packt Publishing: Magento 2 Development Cookbook (https://www.packtpub.com/web-development/magento-2-development-cookbook) Magento 2 Developer's Guide (https://www.packtpub.com/web-development/magento-2-developers-guide) Resources for Article: Further resources on this subject: Social Media in Magento [article] Upgrading from Magneto 1 [article] Social Media and Magento [article]
Read more
  • 0
  • 0
  • 12025

article-image-getting-started-deep-learning
Packt
07 Mar 2016
12 min read
Save for later

Getting Started with Deep Learning

Packt
07 Mar 2016
12 min read
In this article by Joshua F. Wiley, author of the book, R Deep Learning Essentials, we will discuss deep learning, a powerful multilayered architecture for pattern recognition, signal detection, classification, and prediction. Although deep learning is not new, it has gained popularity in the past decade due to the advances in the computational capacity and new ways of efficient training models, as well as the availability of ever growing amount of data. In this article, you will learn what deep learning is. What is deep learning? To understand what deep learning is, perhaps it is easiest to start with what is meant by regular machine learning. In general terms, machine learning is devoted to developing and using algorithms that learn from raw data in order to make predictions. Prediction is a very general term. For example, predictions from machine learning may include predicting how much money a customer will spend at a given company, or whether a particular credit card purchase is fraudulent. Predictions also encompass more general pattern recognition, such as what letters are present in a given image, or whether a picture is of a horse, dog, person, face, building, and so on. Deep learning is a branch of machine learning where a multi-layered (deep) architecture is used to map the relations between inputs or observed features and the outcome. This deep architecture makes deep learning particularly suitable for handling a large number of variables and allows deep learning to generate features as part of the overall learning algorithm, rather than feature creation being a separate step. Deep learning has proven particularly effective in the fields of image recognition (including handwriting as well as photo or object classification) and natural language processing, such as recognizing speech. There are many types of machine learning algorithms. In this article, we are primarily going to focus on neural networks as these have been particularly popular in deep learning. However, this focus does not mean that it is the only technique available in machine learning or even deep learning, nor that other techniques are not valuable or even better suited, depending on the specific task. Conceptual overview of neural networks As their name suggests, neural networks draw their inspiration from neural processes and neurons in the body. Neural networks contain a series of neurons, or nodes, which are interconnected and process input. The connections between neurons are weighted, with these weights based on the function being used and learned from the data. Activation in one set of neurons and the weights (adaptively learned from the data) may then feed into other neurons, and the activation of some final neuron(s) is the prediction. To make this process more concrete, an example from human visual perception may be helpful. The term grandmother cell is used to refer to the concept that somewhere in the brain there is a cell or neuron that responds specifically to a complex and specific object, such as your grandmother. Such specificity would require thousands of cells to represent every unique entity or object we encounter. Instead, it is thought that visual perception occurs by building up more basic pieces into complex representations. For example, the following is a picture of a square: Figure 1 Rather than our visual system having cells neurons that are activated only upon seeing the gestalt, or entirety, of a square, we can have cells that recognize horizontal and vertical lines, as shown in the following: Figure 2 In this hypothetical case, there may be two neurons, one which is activated when it senses horizontal lines and another that is activated when it senses vertical lines. Finally, a higher-order process recognizes that it is seeing a square when both the lower order neurons are activated simultaneously. Neural networks share some of these same concepts, with inputs being processed by a first layer of neurons that may go on to trigger another layer. Neural networks are sometimes shown as graphical models. In Figure 3, Inputs are data represented as squares. These may be pixels in an image or different aspects of sounds, or something else. The next layer of Hidden neurons is neurons that recognize basic features, such as horizontal lines, vertical lines, or curved lines. Finally, the output may be a neuron that is activated by the simultaneous activation of two of the hidden neurons. In this article, observed data or features are depicted as squares, and unobserved or hidden layers as circles: Figure 3 Neural networks are used to refer to a broad class of models and algorithms. Hidden neurons are generated based on some combination of the observed data, similar to a basis expansion in other statistical techniques; however, rather than choosing the form of the expansion, the weights used to create the hidden neurons are learned from the data. Neural networks can involve a variety of activation function(s), which are transformations of the weighted raw data inputs to create the hidden neurons. A common choice for activation functions is the sigmoid function:  and the hyperbolic tangent function . Finally, radial basis functions are sometimes used as they are efficient function approximators. Although there are a variety of these, the Gaussian form is common: . In a shallow neural network such as is shown in Figure 3, with only a single hidden layer, from the hidden units to the outputs is essentially a standard regression or classification problem. The hidden units can be denoted by, h, the outputs by, Y. Different outputs can be denoted by subscripts i = 1, …, k and may represent different possible classifications, such as (in our case) a circle or square. The paths from each hidden unit to each output are the weights and for the ith output are denoted by wi. These weights are also learned from the data, just like the weights used to create the hidden layer. For classification, it is common to use a final transformation, the softmax function, which is   as this ensures that the estimates are positive (using the exponential function) and that the probability of being in any given class sums to one. For linear regression, the identity function, which returns its input, is commonly used. Confusion may arise as to why there are paths between every hidden unit and output as well as every input and hidden unit. These are commonly drawn to represent that a priori any of these relations are allowed to exist. The weights must then be learned from the data, with zero or near zero weights essentially equating to dropping unnecessary relations. This only scratches the surface of the conceptual and practical aspects of neural networks. For a slightly more in-depth introduction to neural networks, see Chapter 11 of The Elements of Statistical Learning, Trevor Hastie, Robert Tibshirani, and Jerome Friedman (2009) also freely available at http://statweb.stanford.edu/~tibs/ElemStatLearn/. Next, we will turn to a brief introduction to deep neural networks. Deep neural networks Perhaps the simplest, if not the most informative, definition of a deep neural network (DNN) is that it is a neural network with multiple hidden layers. Although a relatively simple conceptual extension of neural networks, such deep architecture provides valuable advances in terms of the capability of the models and new challenges in training them. Using multiple hidden layers allows a more sophisticated build-up from simple elements to more complex ones. When discussing neural networks, we considered the outputs to be whether the object was a circle or a square. In a deep neural network, many circles and squares could be combined to form other more advanced shapes. One can consider two complexity aspects of a model's architecture. One is how wide or narrow it is—that is, how many neurons in a given layer. The second is how deep it is, or how many layers of neurons there are. For data that truly has such deep architectures, a DNN can fit it more accurately with fewer parameters than a neural network (NN), because more layers (each with fewer neurons) can be a more efficient and accurate representation; for example, because the shallow NN cannot build more advanced shapes from basic pieces, in order to provide equal accuracy to the DNN it must represent each unique object. Again considering pattern recognition in images, if we are trying to train a model for text recognition the raw data may be pixels from an image. The first layer of neurons could be trained to capture different letters of the alphabet, and then another layer could recognize sets of these letters as words. The advantage is that the second layer does not have to directly learn from the pixels, which are noisy and complex. In contrast, a shallow architecture may require far more parameters, as each hidden neuron would have to be capable of going directly from pixels in an image to a complete word, and many words may overlap, creating redundancy in the model. One of the challenges in training deep neural networks is how to efficiently learn the weights. The models are often complex and local minima abound making the optimization problem a challenging one. One of the major advancements came in 2006, when it was shown that Deep Belief Networks (DBNs) could be trained one layer at a time (Refer A Fast Learning Algorithm for Deep Belief Nets, by Geoffrey E. Hinton, Simon Osindero, and Yee-Whye Teh, (2006) at http://www.cs.toronto.edu/~fritz/absps/ncfast.pdf). A DBN is a type of DNN where multiple hidden layers and connections between (but not within) layers (that is, a neuron in layer 1 may be connected to a neuron in layer 2, but may not be connected to another neuron in layer 1). This is the essentially the same definition of a Restricted Boltzmann Machine (RBM)—an example is diagrammed in Figure 4, except that a RBM typically has one input layer and one hidden layer: Figure 4 The restriction of no connections within a layer is valuable as it allows for much faster training algorithms to be used, such as the contrastive divergence algorithm. If several RBMs are stacked together, they can form a DBN. Essentially, the DBN can then be trained as a series of RBMs. The first RBM layer is trained and used to transform raw data into hidden neurons, which are then treated as a new set of inputs in a second RBM, and the process is repeated until all layers have been trained. The benefits of the realization that DBNs could be trained one layer at a time extend beyond just DBNs, however. DBNs are sometimes used as a pre-training stage for a deep neural network. This allows the comparatively fast, greedy layer-by-layer training to be used to provide good initial estimates, which are then refined in the deep neural network using other, slower, training algorithms such as back propagation. So far we have been primarily focused on feed-forward neural networks, where the results from one layer and neuron feed forward to the next. Before closing this section, two specific kinds of deep neural networks that have grown in popularity are worth mentioning. The first is a Recurrent Neural Network (RNN) where neurons send feedback signals to each other. These feedback loops allow RNNs to work well with sequences. A recent example of an application of RNNs was to automatically generate click-bait such as One trick to great hair salons don't want you to know or Top 10 reasons to visit Los Angeles: #6 will shock you!. RNNs work well for such jobs as they can be seeded from a large initial pool of a few words (even just trending search terms or names) and then predict/generate what the next word should be. This process can be repeated a few times until a short phrase is generated, the click-bait. This example is drawn from a blog post by Lars Eidnes, available at http://larseidnes.com/2015/10/13/auto-generating-clickbait-with-recurrent-neural-networks/. The second type is a Convolutional Neural Network (CNN). CNNs are most commonly used in image recognition. CNNs work by having each neuron respond to overlapping subregions of an image. The benefits of CNNs are that they require comparatively minimal pre-processing yet still do not require too many parameters through weight sharing (for example, across subregions of an image). This is particularly valuable for images as they are often not consistent. For example, imagine ten different people taking a picture of the same desk. Some may be closer or farther away or at positions resulting in essentially the same image having different heights, widths, and the amount of image captured around the focal object. As for neural networks, this description only provides the briefest of overviews as to what DNNs are and some of the use cases to which they can be applied. Summary This article presented a brief introduction to NNs and DNNs. Using multiple hidden layers, DNNs have been a revolution in machine learning by providing a powerful unsupervised learning and feature-extraction component that can be standalone or integrated as part of a supervised model. There are many applications of such models and they are increasingly used by large-scale companies such as Google, Microsoft, and Facebook. Examples of tasks for deep learning are image recognition (for example, automatically tagging faces or identifying keywords for an image), voice recognition, and text translation (for example, to go from English to Spanish, or vice versa). Work is being done on text recognition, such as sentiment analysis to try to identify whether a sentence or paragraph is generally positive or negative, which is particularly useful to evaluate perceptions about a product or service. Imagine being able to scrape reviews and social media for any mention of your product and analyze whether it was being discussed more favorably than the previous month or year or not! Resources for Article:   Further resources on this subject: Dealing with a Mess [article] Design with Spring AOP [article] Probability of R? [article]
Read more
  • 0
  • 0
  • 2402

article-image-common-wlan-protection-mechanisms-and-their-flaws
Packt
07 Mar 2016
19 min read
Save for later

Common WLAN Protection Mechanisms and their Flaws

Packt
07 Mar 2016
19 min read
In this article by Vyacheslav Fadyushin, the author of the book Building a Pentesting Lab for Wireless Networks, we will discuss various WLAN protection mechanisms and the flaws present in them. To be able to protect a wireless network, it is crucial to clearly understand which protection mechanisms exist and which security flaws do they have. This topic will be useful not only for those readers who are new to Wi-Fi security, but also as a refresher for experienced security specialists. (For more resources related to this topic, see here.) Hiding SSID Let's start with one of the common mistakes done by network administrators: relying only on the security by obscurity. In the frames of the current subject, it means using a hidden WLAN SSID (short for service set identification) or simply WLAN name. Hidden SSID means that a WLAN does not send its SSID in broadcast beacons advertising itself and doesn't respond to broadcast probe requests, thus making itself unavailable in the list of networks on Wi-Fi-enabled devices. It also means that normal users do not see that WLAN in their available networks list. But the lack of WLAN advertising does not mean that a SSID is never transmitted in the air—it is actually transmitted in plaintext with a lot of packet between access points and devices connected to them regardless of a security type used. Therefore, SSIDs are always available for all the Wi-Fi network interfaces in a range and visible for any attacker using various passive sniffing tools. MAC filtering To be honest, MAC filtering cannot be even considered as a security or protection mechanism for a wireless network, but it is still called so in various sources. So let's clarify why we cannot call it a security feature. Basically, MAC filtering means allowing only those devices that have MAC addresses from a pre-defined list to connect to a WLAN, and not allowing connections from other devices. MAC addresses are transmitted unencrypted in Wi-Fi and are extremely easy for an attacker to intercept without even being noticed (refer to the following screenshot): An example of wireless traffic sniffing tool easily revealing MAC addresses Keeping in mind the extreme simplicity of changing a physical address (MAC address) of a network interface, it becomes obvious why MAC filtering should not be treated as a reliable security mechanism. MAC filtering can be used to support other security mechanisms, but it should not be used as an only security measure for a WLAN. WEP Wired equivalent privacy (WEP) was born almost 20 years ago at the same time as the Wi-Fi technology and was integrated as a security mechanism for the IEEE 802.11 standard. Like it often happens with new technologies, it soon became clear that WEP contains weaknesses by design and cannot provide reliable security for wireless networks. Several attack techniques were developed by security researchers that allowed them to crack a WEP key in a reasonable time and use it to connect to a WLAN or intercept network communications between WLAN and client devices. Let's briefly review how WEP encryption works and why is it so easy to break. WEP uses so-called initialization vectors (IV) concatenated with a WLAN's shared key to encrypt transmitted packets. After encrypting a network packet, an IV is added to a packet as it is and sent to a receiving side, for example, an access point. This process is depicted in the following flowchart: The WEP encryption process An attacker just needs to collect enough IVs, which is also a trivial task using additional reply attacks to force victims to generate more IVs. Even worse, there are attack techniques that allow an attacker to penetrate WEP-protected WLANs even without connected clients, which makes those WLANs vulnerable by default. Additionally, WEP does not have a cryptographic integrity control, which makes it vulnerable not only to attacks on confidentiality. There are numerous ways how an attacker can abuse a WEP-protected WLAN, for example: Decrypt network traffic using passive sniffing and statistical cryptanalysis Decrypt network traffic using active attacks (reply attack, for example) Traffic injection attacks Unauthorized WLAN access Although WEP was officially superseded by the WPA technology in 2003, it still can be sometimes found in private home networks and even in some corporate networks (mostly belonging to small companies nowadays). But this security technology has become very rare and will not be used anymore in future, largely due to awareness in corporate networks and because manufacturers no longer activate WEP by default on new devices. In our humble opinion, device manufacturers should not include WEP support in their new devices to avoid its usage and increase their customers' security. From the security specialist's point of view, WEP should never be used to protect a WLAN, but it can be used for Wi-Fi security training purposes. Regardless of a security type in use, shared keys always add the additional security risk; users often tend to share keys, thus increasing the risk of key compromise and reducing accountability for key privacy. Moreover, the more devices use the same key, the greater amount of traffic becomes suitable for an attacker during cryptanalytic attacks, increasing their performance and chances of success. This risk can be minimized by using personal identifiers (key, certificate) for users and devices. WPA/WPA2 Due to numerous WEP security flaws, the next generation of Wi-Fi security mechanism became available in 2003: Wi-Fi Protected Access (WPA). It was announced as an intermediate solution until WPA2 is available and contained significant security improvements over WEP. Those improvements include: Stronger encryption Cryptographic integrity control: WPA uses an algorithm called Michael instead of CRC used in WEP. This is supposed to prevent altering data packets on the fly and protects from resending sniffed packets. Usage of temporary keys: The Temporal Key Integrity Protocol (TKIP) automatically changes encryption keys generated for every packet. This is the major improvement over the static WEP where encryption keys should be entered manually in an AP config. TKIP also operates RC4, but the way how it is used was improved. Support of client authentication: The capability to use dedicated authentication servers for user and device authentication made WPA suitable for use in large enterprise networks. The support of cryptographically strong algorithm Advanced Encryption Standard (AES) was implemented in WPA, but it was not set as mandatory, only optional. Although WPA was a significant improvement over WEP, it was a temporary solution before WPA2 was released in 2004 and became mandatory for all new Wi-Fi devices. WPA2 works very similar to WPA and the main differences between WPA and WPA2 is in the algorithms used to provide security: AES became the mandatory algorithm for encryption in WPA2 instead of default RC4 in WPA TKIP used in WPA was replaced by Counter Cipher Mode with Block Chaining Message Authentication Code Protocol (CCMP) Because of the very similar workflows, WPA and WPA2 are also vulnerable to the similar or the same attacks and usually called and spelled in one word WPA/WPA2. Both WPA and WPA2 can work in two modes: pre-shared key (PSK) or personal mode and enterprise mode. Pre-shared key mode Pre-shared key or personal mode was intended for home and small office use where networks have low complexity. We are more than sure that all our readers have met this mode and that most of you use it at home to connect your laptops, mobile phones, tablets, and so on to home networks. The general idea of PSK mode is using the same secret key on an access point and on a client device to authenticate the device and establish an encrypted connection for networking. The process of WPA/WPA2 authentication using a PSK consists of four phases and is also called a 4-way handshake. It is depicted in the following diagram: WPA/WPA2 4-way handshake The main WPA/WPA2 flaw in PSK mode is the possibility to sniff a whole 4-way handshake and brute-force a security key offline without any interaction with a target WLAN. Generally, the security of a WLAN mostly depends on the complexity of a chosen PSK. Computing a PMK (short for primary master key) used in 4-way handshakes (refer to the handshake diagram) is a very time-consuming process compared to other computing operations and computing hundreds of thousands of them can take very long. But in case of a short and low complexity PSK in use, a brute-force attack does not take long even on a not-so-powerful computer. If a key is complex and long enough, cracking it can take much longer, but still there are ways to speed up this process: Using powerful computers with CUDA (short for Compute Unified Device Architecture), which allows a software to directly communicate with GPUs for computing. As GPUs are natively designed to perform mathematical operations and do it much faster than CPUs, the process of cracking works several times faster with CUDA. Using rainbow tables that contain pairs of various PSKs and their corresponding precomputed hashes. They save a lot of time for an attacker because the cracking software just searches for a value from an intercepted 4-way handshake in rainbow tables and returns a key corresponding to the given PMK if there was a match instead of computing PMKs for every possible character combination. Because WLAN SSIDs are used in 4-way handshakes analogous to a cryptographic salt, PMKs for the same key will differ for different SSIDs. This limits the application of rainbow tables to a number of the most popular SSIDs. Using cloud computing is another way to speed up the cracking process, but it usually costs additional money. The more computing power can an attacker rent (or get through another ways), the faster goes the process. There are also online cloud-cracking services available in Internet for various cracking purposes including cracking 4-way handshakes. Furthermore, as with WEP, the more users know a WPA/WPA2 PSK, the greater the risk of compromise—that's why it is also not an option for big complex corporate networks. WPA/WPA2 PSK mode provides the sufficient level of security for home and small office networks only when a key is long and complex enough and is used with a unique (or at least not popular) WLAN SSID. Enterprise mode As it was already mentioned in the previous section, using shared keys itself poses a security risk and in case of WPA/WPA2 highly relies on a key length and complexity. But there are several factors in enterprise networks that should be taken into account when talking about WLAN infrastructure: flexibility, manageability, and accountability. There are various components that implement those functions in big networks, but in the context of our topic, we are mostly interested in two of them: AAA (short for authentication, authorization, and accounting) servers and wireless controllers. WPA-Enterprise or 802.1x mode was designed for enterprise networks where a high security level is needed and the use of AAA server is required. In most cases, a RADIUS server is used as an AAA server and the following EAP (Extensible Authentication Protocol) types are supported (and several more, depending on a wireless device) with WPA/WPA2 to perform authentication: EAP-TLS EAP-TTLS/MSCHAPv2 PEAPv0/EAP-MSCHAPv2 PEAPv1/EAP-GTC PEAP-TLS EAP-FAST You can find a simplified WPA-Enterprise authentication workflow in the following diagram: WPA-Enterprise authentication Depending on an EAP-type configured, WPA-Enterprise can provide various authentication options. The most popular EAP-type (based on our own experience in numerous pentests) is PEAPv0/MSCHAPv2, which is relatively easily integrated with existing Microsoft Active Directory infrastructures and is relatively easy to manage. But this type of WPA-protection is relatively easy to defeat by stealing and bruteforcing user credentials with a rogue access point. The most secure EAP-type (at least, when configured and managed correctly) is EAP-TLS, which employs certificate-based authentication for both users and authentication servers. During this type of authentication, clients also check server's identity and a successful attack with a rogue access point becomes possible only if there are errors in configuration or insecurities in certificates maintenance and distribution. It is recommended to protect enterprise WLANs with WPA-Enterprise in EAP-TLS mode with mutual client and server certificate-based authentication. But this type of security requires additional work and resources. WPS Wi-Fi Protected Setup (WPS) is actually not a security mechanism, but a key exchange mechanism which plays an important role in establishing connections between devices and access points. It was developed to make the process of connecting a device to an access point easier, but it turned out to be one of the biggest wholes in modern WLANs if activated. WPS works with WPA/WPA2-PSK and allows connecting devices to WLANs with one of the following methods: PIN: Entering a PIN on a device. A PIN is usually printed on a sticker at the back side of a Wi-Fi access point. Push button: Special buttons should be pushed on both an access point and a client device during the connection phase. Buttons on devices can be physical and virtual. NFC: A client should bring a device close to an access point to utilize the Near Field Communication technology. USB drive: Necessary connection information exchange between an access point and a device is done using a USB drive. Because WPS PINs are very short and their first and second parts are validated separately, online brute-force attack on a PIN can be done in several hours allowing an attacker to connect to a WLAN. Furthermore, the possibility of offline PIN cracking was found in 2014 which allows attackers to crack pins in 1 to 30 seconds, but it works only on certain devices. You should also not forget that a person who is not permitted to connect to a WLAN but who can physically access a Wi-Fi router or access point can also read and use a PIN or connect via push button method. Getting familiar with the Wi-Fi attack workflow In our opinion (and we hope you agree with us), planning and building a secure WLAN is not possible without the understanding of various attack methods and their workflow. In this topic, we will give you an overview of how attackers work when they are hacking WLANs. General Wi-Fi attack methodology After refreshing our knowledge about wireless threats and Wi-Fi security mechanisms, let's have a look at the attack methodology used by attackers in the real world. Of course, as with all other types of network attack, wireless attack workflows depend on certain situations and targets, but they still align with the following general sequence in almost all cases: The first step is planning. Normally, attackers need to plan what are they going to attack, how can they do it, which tools are necessary for the task, when is the best time and place to attack certain targets, and which configuration templates will be useful so that they can be prepared in advance. White-hat hackers or penetration testers need to set schedules and coordinate project plans with their customers, choose contact persons on a customer side, define project deliverables, and do some other organizational work if demanded. As with every penetration testing project, the better a project was planned (and we can use the word "project" for black-hat hackers' tasks), the more chances of a successful result. The next step is survey. Getting as accurate as possible and as much as possible information about a target is crucial for a successful hack, especially in uncommon network infrastructures. To hack a WLAN or its wireless clients, an attacker would normally collect at least SSIDs or MAC addresses of access points and clients and information about a security type in use. It is also very helpful for an attacker to understand if WPS is enabled on a target access point. All that data allows attackers not only to set proper configs and choose the right options for their tools, but also to choose appropriate attack types and conditions for a certain WLAN or Wi-Fi client. All collected information, especially non-technical (for example, company and department names, brands, or employee names), can also become useful at the cracking phase to build dictionaries for brute-force attacks. Depending on a type of security and attacker's luck, a data collected at the survey phase can even make the active attack phase unnecessary and allow an attacker to proceed directly with the cracking phase. The active attacks phase involves active interaction between an attacker and targets (WLANs and Wi-Fi clients). At this phase, attackers have to create conditions necessary for a chosen attack type and execute it. It includes sending various Wi-Fi management and control frames and installing rogue access points. If an attacker wants to cause a denial of service in a target WLAN as a goal, such attacks are also executed at this phase. Some of active attacks are essential to successfully hack a WLAN, but some of them are intended to just speed up hacking and can be omitted to avoid causing alarm on various wireless intrusion detection/prevention systems (wIDPS), which can possibly be installed in a target network. Thus, the active attacks phase can be called optional. Cracking is another important phase where an attacker cracks 4-way-hadshakes, WEP data, NTLM hashes, and so on, which were intercepted at the previous phases. There are plenty of various free and commercial tools and services including cloud cracking services. In case of success at this phase, an attacker gets the target WLAN's secret(s) and can proceed with connecting to the WLAN, decrypt intercepted traffic, and so on. The active attacking phase Let's have a closer look to the most interesting parts of the active attack phase—WPA-PSK and WPA-Enterprise attacks—in the following topics. WPA-PSK attacks As both WPA and WPA2 are based on the 4-way handshake, attacking them doesn't differ—an attacker needs to sniff a 4-way handshake in the moment, establishing a connection between an access point and an arbitrary wireless client and bruteforcing a matching PSK. It does not matter whose handshake is intercepted, because all clients use the same PSK for a given target WLAN. Sometimes, attackers have to wait long until a device connects to a WLAN to intercept a 4-way handshake and of course they would like to speed up the process when possible. For that purpose, they force already connected device to disconnect from an access point sending control frames (deauthentication attack) on behalf of a target access point. When a device receives such a frame, it disconnects from a WLAN and tries to reconnect again if the "automatic reconnect" feature is enabled (it is enabled by default on most devices), thus performing another one 4-way handshake that can be intercepted by an attacker. Another possibility to hack a WPA-PSK protected network is to crack a WPS PIN if WPS is enabled on a target WLAN. Enterprise WLAN attacks Attacking becomes a little bit more complicated if WPA-Enterprise security is in place, but could be executed in several minutes by a properly prepared attacker by imitating a legitimate access point with a RADIUS server and by gathering user credentials for further analysis (cracking). To settle this attack, an attacker needs to install a rogue access point with a SSID identical to a target WLAN's SSID and set other parameter (like EAP type) similar to the target WLAN to increase chances on success and reduce the probability of the attack to be quickly detected. Most user Wi-Fi devices choose an access point for a connection to a certain WLAN by a signal strength—they connect to that one which has the strongest signal. That is why an attacker needs to use a powerful Wi-Fi interface for a rogue access point to override signals from legitimate ones and make devices around connect to the rogue access point. A RADIUS server used during such attacks should have a capability to record authentication data, NTLM hashes, for example. From a user perspective, being attacked in such way looks just being unable to connect to a WLAN for an unknown reason and could even be not seen if a user is not using a device at the moment and just passing by a rogue access point. It is worth mentioning that classic physical security or wireless IDPS solutions are not always effective in such cases. An attacker or a penetration tester can install a rogue access point outside of the range of a target WLAN. It will allow hacker to attack user devices without the need to get into a physically controlled area (for example, office building), thus making the rogue access point unreachable and invisible for wireless IDPS systems. Such a place could be a bus or train station, parking or a café where a lot of users of a target WLAN go with their Wi-Fi devices. Unlike WPA-PSK with only one key shared between all WLAN users, the Enterprise mode employs personified credentials for each user whose credentials could be more or less complex depending only on a certain user. That is why it is better to collect as many user credentials and hashes as possible thus increasing the chances of successful cracking. Summary In this article, we looked at the security mechanisms that are used to secure access to wireless networks, their typical threads, and common misconfigurations that lead to security breaches and allow attacker to harm corporate and private wireless networks. The brief attack methodology overview has given us a general understanding of how attackers normally act during wireless attacks and how they bypass common security mechanisms by abusing certain flaws in those mechanisms. We also saw that the most secure and preferable way to protect a wireless network is to use WPA2-Enterprise security along with a mutual client and server authentication, which we are going to implement in our penetration testing lab. Resources for Article: Further resources on this subject: Pentesting Using Python [article] Advanced Wireless Sniffing [article] Wireless and Mobile Hacks [article]
Read more
  • 0
  • 0
  • 9789

article-image-enhancing-scripting-experience
Packt
07 Mar 2016
22 min read
Save for later

Enhancing the Scripting Experience

Packt
07 Mar 2016
22 min read
In this article by Chris Halverson, the author of the book, PowerCLI Essentials, has discussed a few important tips on effective scripting. He starts off with a simple everyday example to make you aware of the situation in a humorous manner. Let's take an easy example. Monday morning rolls around and the boss comes into your office with a big smile on his face, "Great report!", he says in his loud booming voice. "The information you provided helped the department secure another $150K for the budget. We are supposed to build a new automation framework that will allow us to produce these types of reports to the management team on a weekly basis." So you reply, "So we got a $150K budget for developing this framework in-house?" The boss chuckles and says, "No, it is for an office renovation. I'm getting my corner window office!" and he walks away laughing. "Typical!" you think. In building an automation framework, there needs to be a methodology to document procedures, create central stores, establish tools, design development standards, and form repositories. Each process takes time and in some cases, capital. However, setting precedence beforehand makes the task of sorting and running scripts later handy and usable. This article deals with the building of a central script store and establishing a means to build consistent and usable scripting experience to provision, report, or configure a virtual environment that is simple and straightforward. We'll be looking on the following topics: Building a code repository Scripting with the intention of repurpose Establishing quality control Code repositories – why would I need that? The first problem that may arise when developing code is that you spend hours designing and writing a script and then, the script is not found. Or you pass the script along to another member of the team and they respond, "It doesn't work". Having a well-defined repository helps to save the definition of the script into an open and robust place. This repository can later be used by everyone in the team to build something new. A repository can consist of a shared folder on a centralized file, a document like SharePoint, a commercial code repository such as CVS or Team Foundation Server, or a public-facing code sharing site such as personal Software Change Manager (SCM) or even a personal blogsite. The value of the repository is dependent upon the sensitivity of the script data being placed in the store. If the scripts are being written with the intention of sharing them with a work associate, a file share may be enough; however, if the scripts are very generic and has no company-sensitive data and there is a desire to get more feedback and more contributors, a public SCM account might be beneficial. Building an internal repository Let's start with a file share layout. Most IT shops have a central server that tends to be a "Jump box" or a utility server that runs general scripts or contains a multitude of administration tools. This server could be set up with a file folder named Scripts that will contain the repository. Next, let's think through the structure. Any good store of scripts should have an area that stores final scripts and scripts under development; it needs a way to label versioning and should have a runtime area that has input files and output files. This enables consistency and provides a means to develop more functionality in the code, while helping to control the script's content and allowing additional functionality to be developed while still allowing the script to be run. So with this in mind, this is an example of a folder structure for Scripts: Scripts     Final        Input        Output        Modules    Test        Input        Output        Modules    Development        Input        Output        Modules Storing the scripts in the main folder will allow a repository to be useful in a layout. Start by building the scripts in the Development folder; once the script is functional, a copy would be placed in the Test folder, and would be available for testing by the remaining operational staff. Once confirmed, the script would be copied to the Final or Production folder. This would allow multiple copies of a script and set for different stages of the code base. The main disadvantage of this is that it quickly becomes unruly and loses its effectiveness once the script repository exceeds a couple of hundred scripts, or the user/developer base exceeds about 10 individuals. This is due to most of the check-in, checkout process. These processes are very manual and prone to overwrites and loss. Other issues such as having multiple people trying to edit the same script at the same time, problems cropping up when versions become out of sync (editing version 1.4 while the script that is in test is version 1.1 and the one in Production is version 1.3), or not knowing what is the latest version to work with. The fact is that there is no way to lock a script and see its history can be some of the biggest issues. Using a third-party tool for code check-in and checkout Downloading and integration aside, there are numerous solutions that could be used to help alleviate the check-in/checkout problem. Using a document management solution such as Microsoft SharePoint or EMC Documentum can resolve some of the version control and sign-in and sign-out issues; however, these can be large and expensive solutions requiring local support staff, and these are truly relatively small issues. If these tools are already running in the environment, look at them as options for the Development portion of the repository. The alternative solution is to utilize a Version Control System (VCS) or Software Change Manager (SCM), which is smaller, has a number of open source forks, and can solve a number of the previously-mentioned issues. As with any solution, there is the typical problem of having another product to learn and another product to support. Any solution that is to be installed in the site needs to be robust and be jointly agreed upon by all the parties that will use it: development, administration, and users. Having one individual that supports and operates a proprietary solution will become either a bottleneck or lose the point of the original solution when that person moves on to a different job. Send it to the cloud! Public-facing script repositories There are a number of places to store code snippets, one-liners, and short examples for a team to view and comment on. Blog sites such as Blogger.com or WordPress can provide a static means of storing scripts and a Wiki can provide a simple collaboration for the team. When these items are shared as a team within a common source, it can be very useful. For most individuals, this static area provides a place to share their experience. GitHub.com is an example of a cloud-based VCS and provides up to a 5-user repository for free. This site adds to the VCS that were mentioned in the previous section and allows scripts to be collaborated through a team whose members may not reside in the same geographic area or in the same time zone. Conclusions No matter what method is chosen, the organization of scripts should be planned beforehand. Planning the structure helps to ensure that whatever automation mechanism is chosen in the future, such as VMware vRealize Automation, VMware vRealize Orchestration or some other custom developed workflow, the scripts will be available to anyone requiring them to run. Scripting with the intention of reuse Changing gears from storing scripts will in fact enable us to repurpose them, or use portions of a script in multiple areas. Functions, workflows, and modules are critical to this end. Each will be described in detail in this section of the book. Functions, functions, functions – the fun with functions What is a function? The help file defines it as a named block of code that performs an action. So writing a function would look like this: Function Get-PS {get-process PowerShell} The output would be nothing unless the function is called like this: Function Get-PS {get-process PowerShell} Get-PS The output of this is the same as Get-Process PowerShell, but it is reusable and could be called at any point in the script. There is a simple and useful function that I personally use in many of the developed scripts to arrive at a decision and return a true or a false value: Function Get-Decision ($Decision) {   Switch ($Decision.toupper()) {     "Y" {$Decision = $True}     "N" {$Decision = $False}     Default {"Enter a ''Y'' for a Yes or a ''N'' for No." ;         Get-Decision ($Decision)}     }   Return ($Decision)   } As you can see, the preceding function is called Get-Decision and accepts an object through Read-Host and returns the decision. So the command that would call this would be something like this. $MakeCSV = Get-Decision $(Read-Host "`nDo you need to make this a CSV to duplicate the settings and create more than one? (Y/N)") So the $MakeCSV variable would be either $True or $False depending on the outcome of the user prompt. Then the next line would do something based upon that decision. Important tip All functions must be before the mainline code. All PoSH runs in a linear fashion from start to end, therefore if the function is being called, it has to be run to enter into the running memory. The function is also removed from memory upon the closing of the command window, so think it through where the function is needed and open it accordingly. An example for a multifunction script is as follows: Premise: Build a script that automates the building of a VM. Inputs: The script should capture the VM name, how many CPUs, how much memory, and build a VM with the settings captured and a 50 GB hard disk. Output: Builds VM. Assumption: $cred is captured using the $cred = Get-Credential command before this script is run. Script: Insert the following code snippet: If ($Cred -ne $null) {   Get-vc vCenter.domain.local -credential $cred |     out-null } Else {   End }   Function Gather-Data {   $Sys = @{     Name = Read-Host "What is the name of the VM?";     NumCPU = Read-Host "What is the amount of CPUs       required?";     MeminGB = Read-Host "How much RAM is required?"     VMHost = get-vmhost | select -first 1   }   Return ($Sys) }   Function Build-VM ($Sys) {   New-VM –Name $Sys.Name –NumCPU $Sys.NumCPU –MemoryGB   $Sys.MeminGB –DiskGB 50 -vmhost $Sys.vmhost }   $output = Gather-Data Build-VM($output) This is a pretty simple example of building a hash table in one function, outputting the hash table, and using it as the input for a second function. The information stored in the hash table is used to populate a New-VM command. The point is that the Gather-Data function can be used to collect data for other things such as a CSV file, or a different function that searches for the information and removes the VM. The best part is that the information is deleted once the window is closed and is useful only when the script is run. Using modules Building modules As building modules are a little more of an advanced topic, this book will only discuss their use. However, a little understanding of what they are may whet your appetite to delve deeper into the topic. MSDN provides an outline of four different module types: the script module, the binary module, the manifest module, and the dynamic module. (https://msdn.microsoft.com/en-us/library/dd878324%28v=vs.85%29.aspx) Primarily, PowerCLI modules have always been typically plug-ins and not modules; they always required a separate running of the PowerCLI icon to allow the use of their cmdlets. Recent versions have changed that mantra and are now using modules. Type Get-Help About_PSSnapins in your PowerShell interface to learn more about the difference. A module is, again as pointed out in the help file, a package of commands. It is a collection of cmdlets, scripts, workflows, aliases, variables, and functions that when imported allow the user to run true and tested commands. Every install of PoSH has modules installed by default. To view the installed modules type Get-Module –ListAvailable and the command will list the installed modules. After the installation of the PowerCLI package, there are a number of modules that are added to the available list of packages. They can be as follows: Directory: C:Program Files (x86)VMwareInfrastructurevSphere PowerCLIModules   ModuleType Version   Name                         ExportedCommands ---------- -------   ----                         ---------------- Binary     6.0.0.0   VMware.VimAutomation.Cis.Core Binary     6.0.0.0   VMware.VimAutomation.Cloud Manifest   6.0.0.0   VMware.VimAutomation.Core Binary     6.0.0.0   VMware.VimAutomation.HA Binary     1.0.0.0   VMware.VimAutomation.License Binary     6.0.0.0   VMware.VimAutomation.PCloud Manifest   6.0.0.0   VMware.VimAutomation.SDK Binary     6.0.0.0   VMware.VimAutomation.Storage Binary     6.0.0.0   VMware.VimAutomation.Vds Binary     1.0.0.0   VMware.VimAutomation.vROps Binary     6.0.0.0   VMware.VumAutomation Each of these modules includes numerous pieces of code that perform various functions with the VMware environment. To list the commands available in a module such as VMware.VimAutomation.Core, run the Get-Command –module VMware.VimAutomation.Core command, where the outputs is, as of PowerCLI v6.0 R3, 291 individual cmdlets. With the use of modules and PoSH v3, importing modules from another system is now a reality. This importing isn't a permanent addition, but can be very handy in a pinch. Firstly, WinRM must be running and configured for remote management; this is done through the WinRM quickconfig command running on an administrative PowerShell window. Once WinRM allows remote connections, type $PS = New-PSSession –Computername <computername>; this allows a remote connection to be established through WinRM to the other computer. Once this PSSession is established, commands can be run on an alternate computer as well as modules can be imported to the local computer. $PS = New-PSSession –ComputerName TestComputer Get-Module –PSSession $PS –ListAvailable This shows the available modules on the remote computer. Adding the Import-Module –PSSession $PS Module_name method will permit the import of a module into the current PoSH window. So if there is no VMware.VimAutomation.Core installed on the local system, the preceding method allows it to run as if it were already installed. The running of the commands become slower as they are run through the remote connection; however, they do run and can get the information needed. Note that this command doesn't transfer the aliases as well, so try and remember its full syntax. Calling other scripts within the script Calling other scripts within a script is fairly straightforward as is a single command. invoke-expression –command .script.ps1 or "c:scriptssample_script.ps1" | invoke-expression, allows an external script to be run and for the output of that script to be captured within the main script. Think about it this way, as the wrapper ps1 or a scripting framework that has been developed it can call another script that another person can write and the output from the external expression. It wouldn't matter what the output would be unless it needs to be parsed and processed for a different output. We will use same the example that was written in the preceding multifunction section, where there was a need to capture the VM name, how many CPUs, and how much memory, and then build a VM with the settings captured and on a 50 GB hard disk. An example of a framework script is as follows: Premise: Build a script that automates the building of a VM. Inputs: The script should capture the VM name, how many CPUs, how much memory, and then build a VM with the settings captured and a 50 GB Hard Disk. Output: Builds VM. Assumption: This script must call other scripts through invoke-expression. Script: Insert the following code snippet: Connect-vCenter.ps1<# .Synopsis   Does the lifting of connecting to a vCenter .Description   Starts VIMAutomation Module   Gets Credentials   Gets the vCenter name and connects to vCenter .Input   User Input     Credentials     vCenter Name .Output   None .Author   Chris Halverson .Change Log   11/6/2015 .FileName   Connect-vCenter.ps1 .Version   Draft 0.1 #>   #Call the Module If ($(get-module -ListAvailable) –notmatch`   "VMware.VimAutomation.Core") {     Import-Module VMware.vimautomation.core }   #Test for stored credentials If ($Cred -ne $null){   write-Host 'Using the Credential '$Cred.UserName } Else {   $Cred = Get-Credential } $VC = Read-Host "What is the name of the vCenter server? "   #Trying a ping of the vCenter Host If (Test-Connection -ComputerName $VC -Count 2 -quiet) {   Connect-ViServer $VC -Credential $Cred | Out-Null   Write-Host "Connected to vCenter $VC " -ForegroundColor     Green   [Console]::Foregroundcolor = "Gray" } Else {   Write-Host "vCenter not found. Exiting script" `     -ForegroundColor Red   [console]::ForegroundColor = "Gray"   Break} Gather-Data.ps1 <# .Synopsis   Collects Information for build data .Description   Gets Appropriate data and outputs to a variable .Input   User Input     VM Name     Number of CPUs     Amount of RAM in GB .Output   Variable .Author   Chris Halverson .Change Log   11/6/2015 .FileName   Gather-Data.ps1 .Version   Draft 0.1 #>   $global:Sys = @{   Name = Read-Host "What is the name of the VM?";   NumCPU = Read-Host "What is the amount of CPUs     required?";   MeminGB = Read-Host "How much RAM is required?" }   Build-VM.ps1   <# .Synopsis   Builds a VM .Description   Calls the Connect-vCenter.ps1 Script to connect to     vCenter   Gathers Data from Gather-Data.ps1   Builds VM based on Specs .Input   Called through other Scripts .Output   Builds VM .Author   Chris Halverson .Change Log   11/6/2015 .FileName   Build-VM.ps1 .Version   Draft 0.1 #>   Invoke-Expression -command .Connect-vCenter.ps1 Invoke-Expression -command .Gather-Data.ps1   $vHost = Get-VMhost | Select -first 1   New-VM –Name $Sys.Name –NumCPU $Sys.NumCPU –MemoryGB $Sys.MeminGB ` –DiskGB 50 -vmhost $vhost Upon completion of the Build-VM.ps1 script, a new VM is created and although the Guest OS type is Windows XP and some of the other configuration is a little off from what a typical build would be, the script was successful and it has components that can be reused in a loop or a workflow. Building a framework that others can build upon A framework in this context is a set of standard components that every other script that has been developed would want to access. For example, building a wrapper that can do email a final output without running the command and specifying certain information, or something that automatically opens the connection to the vCenter's environment. These are some of the things that building a wrapper or workflow can do. Some of the advantages of workflows are that they can run parallel instead of serially as compared to a standard PowerShell script; they can be paused, stopped, or restarted as needed, and they can be run on remote hosts and can increase the performance ten times if there are enough remote engines to run it. Logging is included in the workflow engine. These become huge as more and more administrative tasks need to have parallelism to run properly. One important thing of note is that workflows are built using the .NET framework Windows Workflow Foundation (WWF), and the PowerShell code that is being run in the workflow is actually being translated into XAML for WWF. The XAML code can actually be seen when a workflow is created by typing this: get-command [Workflow name] | select-object XamlDefinition Typing Help About_Workflows gives a lengthy bit of information that discusses what a workflow is, its benefits, and why it is are needed: ABOUT WORKFLOWS    Workflows are commands that consist of an ordered sequence of    related activities. Typically, they run for an extended period    of time, gathering data from and making changes to hundreds of    computers, often in heterogeneous environments.      Workflows can be written in XAML, the language used in Windows    Workflow Foundation, or in the Windows PowerShell language.    Workflows are typically packaged in modules and include help      Workflows are critical in an IT environment because they can    survive reboots and recover automatically from common failures.    You can disconnect and reconnect from sessions and computers    running workflows without interrupting workflow processing,    and suspend and resume workflows transparently without data    loss. Each activity in a workflow can be logged and audited    for reference. Workflow can run as jobs and can be scheduled    by using the Scheduled Jobs feature of Windows PowerShell.      The state and data in a workflow is saved or "persisted" at    the beginning and end of the workflow and at points that you    specify. Workflow persistence points work like database    snapshots    or program checkpoints to protect the workflow from the    effects    of interruptions and failures. In the case of a failure from    which the workflow cannot recover, you can use the persisted    data and resume from the last persistence point, instead of    rerunning an extensive workflow from the beginning. So to add to the description from the help file, these are jobs or scheduled jobs that can be started, run, rerun and be paused for a reboot. The workflow engine should use PoSH v3 and higher to run, as it gains many advantages when run through these jobs. The workflow requires the following: A client computer to run the workflow A workflow session (a PowerShell session otherwise known as a PSSession) on the client computer (it can be local or remote) And a target for the workflow activities Running a workflow To run a workflow, there are some caveats to make sure things run smoothly. Firstly, make sure that PowerShell is running in an administrative window or option. Either right-click on the PowerShell icon and select Run as Administrator (which triggers an User Access Control or UAC verification window), or type Start-Process PowerShell –verb RunAs that does the same thing. Next, enable the client or the remote client to have a remote PSSession run by typing Enable-PSRemoting –Force or Set-WSManQuickConfig or as seen in a previous section, type WinRM QuickConfig, which allows the computer to accept WinRM or remote management commands. These commands will start the WinRM service, configure a firewall exception for the service, and allow Kerberos authentication for the commands to be run. To return the configuration back Disable-PSRemoting –force returns the configuration back to the original condition of the OS. A typical way to set up a remote session is to use the New-PSWorkflowSession cmdlet. Let's see what this actually looks like and then process a simple workflow script. Premise: Build a workflow that gets a WMI entry for Win32_BIOS, lists running processes, lists the stopped services on the computer, and does all that in parallel. Inputs: All inputs will be hardcoded for simplicity. Output: The contents of the Win32_BIOS processes that are running and the stopped services. Assumption: That a workflow is being used. Script: Insert the following code snippet: Workflow Workflow pTest {   Parallel {     Get-CimInstance -ClassName Win32_Bios         Get-Process | Select Id, ProcessName     Get-Service | ? Status –match "Stopped" |Select       DisplayName   } } When this workflow is run, it is easy to see that these commands are run in parallel, as the output is not displayed in the order of execution. In fact, the CimInstance completes first, then the services and finally, the processes, and export outputs shows these were run in parallel. The order would change depending on what completes first. These workflows will be developed more when we mix VMware administration scripts with Windows administration scripts to fill out more of remote development. Summary This article summarized good coding practices, outlined the use of repeatable code, and ways to use that code for other general use. It built a longer code base and methods to keep the practicalities from the concept and transform the thought to action. This article also summed up a version control technique to keep historical information into the script management structure. Further resources on this subject: Introduction to vSphere Distributed switches Creating Custom Reports and Notifications for vSphere Creating an Image Profile by cloning an existing one
Read more
  • 0
  • 0
  • 4107
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-docker-hosts
Packt
07 Mar 2016
19 min read
Save for later

Docker Hosts

Packt
07 Mar 2016
19 min read
In this article by Scott Gallagher, the author of Securing Docker, we are glad you decided to read this article and we want to make sure that the resources you are using are being secured in proper ways to ensure system integrity and data loss prevention. It is also important to understand why you should care about the security. If data loss prevention doesn't scare you already, thinking about the worst possible scenario—a full system compromise and the possibility of your secret designs being leaked or stolen by others—might help to reinforce security. In this article, we will be taking a look at securing Docker hosts and will be covering the following topics: Docker host overview Discussing Docker host Virtualization and isolation Attack surface of Docker daemon Securing Docker hosts Docker Machine SELinux and AppArmor Auto-patching hosts (For more resources related to this topic, see here.) Docker host overview Before we get in depth and dive in, let's first take a step back and review exactly what the Docker host is. In this section, we will look at the Docker host itself to get an understanding of what we are referring to when we are talking about the Docker host. We will also be looking at the virtualization and isolation that Docker uses to ensure security. Discussing Docker host When we think of a Docker host, what comes to our mind? If you put it in terms of virtual machines that almost all of us are familiar with, we would then compare what a VM host is compared with a Docker host. A VM host is what the virtual machines actually run on top of. Typically, this is something like VMware ESXi if you are using VMware or Windows Server if you are using Hyper-V. Let's take a look at how they are as compared so that you can get a visual representation of the two, as shown in the following diagram: The preceding image depicts the similarities between a VM host and Docker host. As stated previously, the host of any service is simply the system that the underlying virtual machines or containers in Docker run on top of. Therefore, a host is the operating system or service that contains and operates the underlying systems that you install and set up a service on such as web servers, databases, and more. Virtualization and isolation To understand how Docker hosts can be secured, we must first understand how the Docker host is set up and what items are contained in the Docker host. Again, like VM hosts, they contain the operating system that the underlying service operates on. With VMs, you are creating a whole new operating system on top of this VM host operating system. However, on Docker, you are not doing that and are sharing the Linux kernel that the Docker host is using. Let's take a look at the following diagram to help us represent this: As we can see from the preceding image, there is a distinct difference between how items are set up on a VM host and on a Docker host. On a VM host, each virtual machine has all of its own items inclusive to itself. Each containerized application brings its own set of libraries, whether it is Windows or Linux. Now, on the Docker host, we don't see that. We see that they share the Linux kernel version that is being used on the Docker host. That being said, there are some security aspects that need to be addressed on the Docker host side of things. Now, on the VM host side, if someone does compromise a virtual machine, the operating system is isolated to just that one virtual machine. Back on the Docker host side of things, if the kernel is compromised on the Docker host, then all the containers running on that host are now at high risk as well. So, now you should see how important it is that we focus on security when it comes to Docker hosts. Docker hosts do use some isolation that will help protect against kernel or container compromises in a few ways. Two of these ways are by implementing namespaces and cgroups. Before we can discuss how they help, let's first give a definition for each of them. Kernel namespaces as they are commonly known as provide a form of isolation for the containers that will be running on your hosts. What does this mean? This means that each container that you run on top of your Docker hosts will be given its own network stack so that it doesn't get privileged access to another containers socket or interfaces. However, by default, all Docker containers are sitting on the bridged interface so that they can communicate with each other easily. Think of the bridged interface as a network switch that all the containers are connected to. Namespaces also provide isolation for processes and mount isolation. Processes running in one container can't affect or even see processes running in another Docker container. Isolation for mount points is also on a container by container basis. This means that mount points on one container can't see or interact with mount points on another container. On the other hand, control groups are what control and limit resources for containers that will be running on top of your Docker hosts. What does this boil down to, meaning how will it benefit you? It means that cgroups, as they will be called going forward, help each container get its fair share of memory disk I/O, CPU, and much more. So, a container cannot bring down an entire host by exhausting all the resources available on it. This will help to ensure that even if an application is misbehaving that the other containers won't be affected by this application and your other applications can be assured uptime. Attack surface of Docker daemon While Docker does ease some of the complicated work in the virtualization world, it is easy to forget to think about the security implications of running containers on your Docker hosts. The largest concern you need to be aware of is that Docker requires root privileges to operate. For this reason, you need to be aware of who has access to your Docker hosts and the Docker daemon as they will have full administrative access to all your Docker containers and images on your Docker host. They can start new containers, stop existing ones, remove images, pull new images, and even reconfigure running containers as well by injecting commands into them. They can also extract sensitive information like passwords and certificates from the containers. For this reason, make sure to also separate important containers if you do need to keep separate controls on who has access to your Docker daemon. This is for containers where people have a need for access to the Docker host where the containers are running. If a user needs API access then that is different and separation might not be necessary. For example, keep containers that are sensitive on one Docker host, while keeping normal operation containers running on another Docker host and grant permissions for other staff access to the Docker daemon on the unprivileged host. If possible, it is also recommended to drop the setuid and setgid capabilities from containers that will be running on your hosts. If you are going to run Docker, it's recommended to only use Docker on this server and not other applications. Docker also starts containers with a very restricted set of capabilities, which helps in your favor to address security concerns. To drop the setuid or setgid capabilities when you start a Docker container you will do something similar to the following: $ docker run -d --cap-drop SETGID --cap-drop SETUID nginx This would start the nginx container and would drop the SETGID and SETUID capabilities for the container. Docker's end goal is to map the root user to a non-root user that exists on the Docker host. They also are working towards allowing the Docker daemon to run without requiring root privileges. These future improvements will only help facilitate how much focus Docker does take when they are implementing their feature sets. Protecting the Docker daemon To protect the Docker daemon even more, we can secure the communications that our Docker daemon is using. We can do this by generating certificates and keys. There are are few terms to understand before we dive into the creation of the certificates and keys. A Certificate Authority (CA) is an entity that issues certificates. This certificate certifies the ownership of the public key by the subject that is specified in the certificate. By doing this, we can ensure that your Docker daemon will only accept communication from other daemons that have a certificate that was also signed by the same CA. Now, we will be looking at how to ensure that the containers you will be running on top of your Docker hosts will be secure in a few pages; however, first and foremost, you want to make sure the Docker daemon is running securely. To do this, there are some parameters you will need to enable for when the daemon starts. Some of the things you will need beforehand will be as follows: Create a CA. $ openssl genrsa -aes256 -out ca-key.pem 4096 Generating RSA private key, 4096 bit long modulus ......................................................................................................................................................................................................................++ ....................................................................++ e is 65537 (0x10001) Enter pass phrase for ca-key.pem: Verifying - Enter pass phrase for ca-key.pem: You will need to specify two values, pass phrase and pass phrase. This needs to be between 4 and 1023 characters. Anything less than 4 or more than 1023 won't be accepted. $ openssl req -new -x509 -days <number_of_days> -key ca-key.pem -sha256 -out ca.pem Enter pass phrase for ca-key.pem: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:Pennsylvania Locality Name (eg, city) []: Organization Name (eg, company) [Internet Widgits Pty Ltd]: Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []: Email Address []: There are a couple of items you will need. You will need pass phrase you entered earlier for ca-key.pem. You will also need the Country, State, city, Organization Name, Organizational Unit Name, fully qualified domain name (FQDN), and Email Address; to be able to finalize the certificate. Create a client key and signing certificate. $ openssl genrsa -out key.pem 4096 $ openssl req -subj '/CN=<client_DNS_name>' -new -key key.pem -out client.csr Sign the public key. $ openssl x509 -req -days <number_of_days> -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.em Change permissions. $ chmod -v 0400 ca-key.pem key.pem server-key.em $ chmod -v 0444 ca.pem server-cert.pem cert.em Now, you can make sure that your Docker daemon only accepts connections from these that you provide the signed certificates to: $ docker daemon --tlsverify --tlscacert=ca.pem --tlscert=server-certificate.pem --tlskey=server-key.pem -H=0.0.0.0:2376 Make sure that the certificate files are in the directory you are running the command from or you will need to specify the full path to the certificate file. On each client, you will need to run the following: $ docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem -H=<$DOCKER_HOST>:2376 version Again, the location of the certificates is important. Make sure to either have them in a directory where you plan to run the preceding command or specify the full path to the certificate and key file locations. You can read more about using TLS by default with your Docker daemon by going to the following link:http://docs.docker.com/engine/articles/https/ For more reading on Docker Secure Deployment Guidelines, the following link provides a table that can be used to gain insight into some other items you can utilize as well:https://github.com/GDSSecurity/Docker-Secure-Deployment-Guidelines Some of the highlights from that website are: Collecting security and audit logs Utilizing the privileged switch when running Docker containers Device control groups Mount points Security audits Securing Docker hosts Where do we start to secure our hosts? What tools do we need to start with? We will take a look at using Docker Machine in this section and how to ensure the hosts that we are creating are being created in a secure manner. Docker hosts are like the front door of your house, if you don't secure them properly, then anybody can just walk right in. We will also take a look at Security-Enhanced Linux (SELinux) and AppArmor to ensure that you have an extra layer of security on top of the hosts that you are creating. Lastly, we will take a look at some of the operating systems that support and do auto patching of their operating systems when a security vulnerability is discovered. Docker Machine Docker Machine is the tool that allows you to install the Docker daemon onto your virtual hosts. You can then manage these Docker hosts with Docker Machine. Docker Machine can be installed either through the Docker Toolbox on Windows and Mac. If you are using Linux, you will install Docker Machine through a simple curl command: $ curl -L https://github.com/docker/machine/releases/download/v0.6.0/docker-machine-`uname -s`-`uname -m` > /usr/local/bin/docker-machine && $ chmod +x /usr/local/bin/docker-machine The first command installs Docker Machine into the /usr/local/bin directory and the second command changes the permissions on the file and sets it to executable. We will be using Docker Machine in the following walkthrough to set up a new Docker host. Docker Machine is what you should be or will be using to set up your hosts. For this reason, we will start with it to ensure your hosts are set up in a secure manner. We will take a look at how you can tell if your hosts are secure when you create them using the Docker Machine tool. Let's take a look at what it looks like when you create a Docker host using Docker Machine, as follows: $ docker-machine create --driver virtualbox host1 Running pre-create checks... Creating machine... Waiting for machine to be running, this may take a few minutes... Machine is running, waiting for SSH to be available... Detecting operating system of created instance... Provisioning created instance... Copying certs to the local machine directory... Copying certs to the remote machine...   Setting Docker configuration on the remote daemon... From the preceding output, as the create is running, it is doing things such as creating the machine, waiting for SSH to become available, performing actions, copying the certificates to the correct location, and setting up the Docker configuration, as follows: To see how to connect Docker to this machine, run: docker-machine env host1 $ docker-machine env host1 export DOCKER_TLS_VERIFY="1" export DOCKER_HOST="tcp://192.168.99.100:2376" export DOCKER_CERT_PATH="/Users/scottpgallagher/.docker/machine/machines/host1" export DOCKER_MACHINE_NAME="host1" # Run this command to configure your shell: # eval "$(docker-machine env host1)" The preceding commands output shows the commands that were run to set this machine up as the one that Docker commands will now run against:  eval "$(docker-machine env host1)" We can now run the regular Docker commands, such as docker info, and it will return information from host1, now that we have set it as our environment. We can see from the preceding highlighted output that the host is being set up secure from the start from two of the export lines. Here is the first highlighted line by itself: export DOCKER_TLS_VERIFY="1" From the other highlighted output, DOCKER_TLS_VERIFY is being set to 1 or true. Here is the second highlighted line by itself: export DOCKER_HOST="tcp://192.168.99.100:2376" We are setting the host to operate on the secure port of 2376 as opposed to the insecure port of 2375. We can also gain this information by running the following command: $ docker-machine ls NAME      ACTIVE   DRIVER       STATE     URL                         SWARM                     host1              *        virtualbox     Running   tcp://192.168.99.100:2376   Make sure to check the TLS switch options that can be used with Docker Machine if you have used the previous instructions to setup your Docker hosts and Docker containers to use TLS. These switches would be helpful if you have existing certificates that you want to use as well. These switches can be found by running the following command: $ docker-machine --help   Options:   --debug, -D      Enable debug mode   -s, --storage-path "/Users/scottpgallagher/.docker/machine"   Configures storage path [$MACHINE_STORAGE_PATH]   --tls-ca-cert      CA to verify remotes against [$MACHINE_TLS_CA_CERT]   --tls-ca-key      Private key to generate certificates [$MACHINE_TLS_CA_KEY]   --tls-client-cert     Client cert to use for TLS [$MACHINE_TLS_CLIENT_CERT]   --tls-client-key       Private key used in client TLS auth [$MACHINE_TLS_CLIENT_KEY]   --github-api-token     Token to use for requests to the Github API [$MACHINE_GITHUB_API_TOKEN]   --native-ssh      Use the native (Go-based) SSH implementation. [$MACHINE_NATIVE_SSH]   --help, -h      show help   --version, -v      print the version You can also regenerate TLS certificates for a machine using the regenerate-certs subcommand in the event that you want that peace of mind or that your keys do get compromised. An example command would look similar to the following command: $ docker-machine regenerate-certs host1    Regenerate TLS machine certs?  Warning: this is irreversible. (y/n): y Regenerating TLS certificates Copying certs to the local machine directory... Copying certs to the remote machine... Setting Docker configuration on the remote daemon... SELinux and AppArmor Most Linux operating systems are based on the fact that they can leverage SELinux or AppArmor for more advanced access controls to files or locations on the operating system. With these components, you can limit a containers ability to execute a program as the root user with root privileges. Docker does ship a security model template that comes with AppArmor and Red Hat comes with SELinux policies as well for Docker. You can utilize these provided templates to add an additional layer of security on top of your environments. For more information about SELinux and Docker, I would recommend visiting the following website: https://www.mankier.com/8/docker_selinux While, on the other hand, if you are in the market for some more reading on AppArmor and Docker, I would recommend visiting the following website: https://github.com/docker/docker/tree/master/contrib/apparmor Here you will find a template.go file, which is the template that Docker ships with its application that is the AppArmor template. Auto-patching hosts If you really want to get into advanced Docker hosts, then you could use CoreOS and Amazon Linux AMI, which perform auto-patching, both in a different way. While CoreOS will patch your operating system when a security update comes out and will reboot your operating system, the Amazon Linux AMI will complete the updates when you reboot. So when choosing which operating system to use when you are setting up your Docker hosts, make sure to take into account the fact that both of these operating system implement some form of auto-patching, but in a different way. You will want to make sure you are implementing some type of scaling or failover to address the needs of something that is running on CoreOS so that there is no downtime when a reboot occurs to patch the operating system. Summary In this article, we looked at how to secure our Docker hosts. The Docker hosts are the fire line of defense as they are the starting point where your containers will be running and communicating with each other and end users. If these aren't secure, then there is no purpose of moving forward with anything else. You learned how to set up the Docker daemon to run securely running TLS by generating the appropriate certificates for both the host and the clients. We also looked at the virtualization and isolation benefits of using Docker containers, but make sure to remember the attack surface of the Docker daemon too. Other items included how to use Docker Machine to easily create Docker hosts on secure operating systems with secure communication and ensure that they are being setup using secure methods when you use it to setup your containers. Using items such as SELinux and AppArmor also help to improve your security footprint as well. Lastly, we covered some Docker host operating systems that you can use for auto-patching as well, such as CoreOS and Amazon Linux AMI. Resources for Article:   Further resources on this subject: Understanding Docker [article] Hands On with Docker Swarm [article] Introduction to Docker [article]
Read more
  • 0
  • 0
  • 3190

article-image-common-grunt-plugins
Packt
07 Mar 2016
9 min read
Save for later

Common Grunt Plugins

Packt
07 Mar 2016
9 min read
In this article, by Douglas Reynolds author of the book Learning Grunt, you will learn about Grunt plugins as they are core of the Grunt functionality and are an important aspect of Grunt as plugins are what we use in order to design an automated build process. (For more resources related to this topic, see here.) Common Grunt plugins and their purposes At this point, you should be asking yourself, what plugins can benefit me the most and why? Once you ask these questions, you may find that a natural response will be to ask further questions such as "what plugins are available?" This is exactly the intended purpose of this section, to introduce useful Grunt plugins and describe their intended purpose. contrib-watch This is, in the author's opinion, probably the most useful plugin available. The contrib-watch plugin responds to changes in files defined by you and runs additional tasks upon being triggered by the changed file events. For example, let's say that you make changes to a JavaScript file. When you save, and these changes are persisted, contrib-watch will detect that the file being watched has changed. An example workflow might be to make and save changes in a JavaScript file, then run Lint on the file. You might paste the code into a Lint tool, such as http://www.jslint.com/, or you might run an editor plugin tool on the file to ensure that your code is valid and has no defined errors. Using Grunt and contrib-watch, you can configure contrib-watch to automatically run a Grunt linting plugin so that every time you make changes to your JavaScript files, they are automatically lined. Installation of contrib-watch is straight forward and accomplished using the following npm-install command: npm install grunt-contrib-watch –save-dev The contrib-watch plugin will now be installed into your node-module directory. This will be located in the root of your project, you may see the Angular-Seed project for an example. Additionally, contrib-watch will be registered in package.json, you will see something similar to the following in package.json when you actually run this command: "devDependencies": { "grunt": "~0.4.5", "grunt-contrib-watch": "~0.4.0" } Notice the tilde character (~) in the grunt-contrib-watch: 0.5.3 line, the tilde actually specifies that the most recent minor version should be used when updating. Therefore, for instance, if you updated your npm package for the project, it would use 0.5.4 if available; however, it would not use 0.6.x as that is a higher minor version. There is also a caret character (^) that you may see. It will allow updates matching the most recent major version. In the case of the 0.5.3 example, 0.6.3 will be allowed, while 1.x versions are not allowed. At this point, contrib-watch is ready to be configured into your project in a gruntfile, we will look more into the gruntfile later. It should be noted that this, and many other tasks, can be run manually. In the case of contrib-watch, once installed and configured, you can run the grunt watch command to start watching the files. It will continue to watch until you end your session. The contrib-watch has some useful options. While we won't cover all of the available options, the following are some notable options that you should be aware of. Make sure to review the documentation for the full listing of options: Options.event: This will allow you to configure contrib-watch to only trigger when certain event types occur. The available types are all, changed, added, and deleted. You may configure more than one type if you wish. The all will trigger any file change, added will respond to new files added, and deleted will be triggered on removal of a file. Options.reload: This will trigger the reload of the watch task when any of the watched files change. A good example of this is when the file in which the watch is configured changes, it is called gruntfile.js. This will reload the gruntfile and restart contrib-watch, watching the new version of gruntfile.js. Options.livereload: This is different than reload, therefore, don't confuse the two. Livereload starts a server that enables live reloading. What this means is that when files are changed, your server will automatically update with the changed files. Take, for instance, a web application running in a browser. Rather than saving your files and refreshing your browser to get the changed files, livereload automatically reloads your app in the browser for you. contrib-jshint The contrib-jshint plugin is to run automated JavaScript error detection and will help with identifying potential problems in your code, which may surface during the runtime. When the plugin is run, it will scan your JavaScript code and issue warnings on the preconfigured options. There are a large number of error messages that jshint might provide and it can be difficult at times to understand what exactly a particular message might be referring to. Some examples are shown in the following: The array literal notation [] is preferable The {a} is already defined Avoid arguments.{a} Bad assignment Confusing minuses The list goes on and there are resources such as http://jslinterrors.com/, whose purpose is to help you understand what a particular warning/error message means. Installation of contrib-jshint follows the same pattern as other plugins, using npm to install the plugin in your project, as shown in the following: npm install grunt-contrib-jshint --save-dev This will install the contrib-jshint plugin in your project's node-modules directory and register the plugin in your devDependencies section of the package.json file at the root of your project. It will be similar to the following: "devDependencies": { "grunt": "~0.4.5", "grunt-contrib-jshint": "~0.4.5" } Similar to the other plugins, you may manually run contrib-jshint using the grunt jshint command. The contrib-jshint is jshint, therefore, any of the options available in jshint may be passed to contrib-jshint. Take a look at http://jshint.com/docs/options/ for a complete listing of the jshint options. Options are configured in the gruntfile.js file that we will cover in detail later in this book. Some examples of options are as follows: curly: This enforces that curly braces are used in code blocks undef: This ensures that all the variables have been declared maxparams: This checks to make sure that the number of arguments in a method does not exceed a certain limit The contrib-jshint allows you to configure the files that will be linted, the order in which the linting will occur, and even control linting before and after the concatenation. Additionally, contrib-jshint allows you to suppress warnings in the configuration options using the ignore_warning option. contrib-uglify Compression and minification are important for reducing the file sizes and contributing for better loading times to improve the performance. The contrib-uglify plugin provides the compression and minification utility by optimizing the JavaScript code and removing unneeded line breaks and whitespaces. It does this by parsing JavaScript and outputting regenerated, optimized, and code with shortened variable names for example. The contrib-uglify plugin is installed in your project using the npm install command, just as you will see with all the other Grunt plugins, as follows: npm install grunt-contrib-uglify --save-dev After you run this command, contrib-uglify will be installed in your node-modules directory at the root of your application. The plugin will also be registered in your devDependencies section of package.json. You should see something similar to the following in devDependencies: "devDependencies": { "grunt": "~0.4.5", "grunt-contrib-uglify": "~0.4.0" } In addition to running as an automated task, contrib-uglify plugin may be run manually by issuing the grunt uglify command. The contrib-uglify plugin is configured to process specific files as defined in the gruntfile.js configuration file. Additionally, contrib-uglify will have defined output destination files that will be created for the processed minified JavaScript. There is also a beautify option that can be used to revert the minified code, should you wish to easily debug your JavaScript. A useful option that is available in conntrib-uglify is banners. Banners allow you to configure banner comments to be added to the minified output files. For example, a banner could be created with the current date and time, author, version number, and any other important information that should be included. You may reference your package.json file in order to get information, such as the package name and version, directly from the package.json configuration file. Another notable option is the ability to configure directory-level compiling of files. You achieve this through the configuration of the files option to use wildcard path references with file extension, such as **/*.js. This is useful when you want to minify all the contents in a directory. contrib-less The contrib-less is a plugin that compiles LESS files into CSS files. The LESS provides extensibility to standard CSS by allowing variables, mixins (declaring a group of style declarations at once that can be reused anywhere in the stylesheet), and even conditional logic to manage styles throughout the document. Just as with other plugins, contrib-less is installed to your project using the npm install command with the following command: npm install grunt-contrib-less –save-dev The npm install will add contrib-less to your node-modules directory, located at the root of your application. As we are using --save-dev, the task will be registered in devDependencies of package.json. The registration will look something similar to the following: "devDependencies": { "grunt": "~0.4.5", "grunt-contrib-less": "~0.4.5" } Typical of Grunt tasks, you may also run contrib-less manually using the grunt less command. The contrib-less will be configured using the path and file options to define the location of source and destination output files. The contrib-less plugin can also be configured with multiple environment-type options, for example dev, test, and production, in order to apply different options that may be needed for different environments. Some typical options used in contrib-less include the following: paths: These are the directories that should be scanned compress: This shows whether to compress output to remove the whitespace plugins: This is the mechanism for including additional plugins in the flow of processing banner: This shows the banner to use in the compiled destination files There are several more options that are not listed here, make sure to refer to the documentation for the full listing of contrib-less options and example usage. Summary In this article we have covered some basic grunt plugins. Resources for Article: Further resources on this subject: Grunt in Action [article] Optimizing JavaScript for iOS Hybrid Apps [article] Welcome to JavaScript in the full stack [article]
Read more
  • 0
  • 0
  • 10490

article-image-app-development-using-react-native-vs-androidios
Manuel Nakamurakare
03 Mar 2016
6 min read
Save for later

App Development Using React Native vs. Android/iOS

Manuel Nakamurakare
03 Mar 2016
6 min read
Until two years ago, I had exclusively done Android native development. I had never developed iOS apps, but that changed last year, when my company decided that I had to learn iOS development. I was super excited at first, but all that excitement started to fade away as I started developing our iOS app and I quickly saw how my productivity was declining. I realized I had to basically re-learn everything I learnt in Android: the framework, the tools, the IDE, etc. I am a person who likes going to meetups, so suddenly I started going to both Android and iOS meetups. I needed to keep up-to-date with the latest features in both platforms. It was very time-consuming and at the same time somewhat frustrating since I was feeling my learning pace was not fast enough. Then, React Native for iOS came out. We didn’t start using it until mid 2015. We started playing around with it and we really liked it. What is React Native? React Native is a technology created by Facebook. It allows developers to use JavaScript in order to create mobile apps in both Android and iOS that look, feel, and are native. A good way to explain how it works is to think of it as a wrapper of native code. There are many components that have been created that are basically wrapping the native iOS or Android functionality. React Native has been gaining a lot of traction since it was released because it has basically changed the game in many ways. Two Ecosystems One reason why mobile development is so difficult and time consuming is the fact that two entirely different ecosystems need to be learned. If you want to develop an iOS app, then you need to learn Swift or Objective-C and Cocoa Touch. If you want to develop Android apps, you need to learn Java and the Android SDK. I have written code in the three languages, Swift, Objective C, and Java. I don’t really want to get into the argument of comparing which of these is better. However, what I can say is that they are different and learning each of them takes a considerable amount of time. A similar thing happens with the frameworks: Cocoa Touch and the Android SDK. Of course, with each of these frameworks, there is also a big bag of other tools such as testing tools, libraries, packages, etc. And we are not even considering that developers need to stay up-to-date with the latest features each ecosystem offers. On the other hand, if you choose to develop on React Native, you will, most of the time, only need to learn one set of tools. It is true that there are many things that you will need to get familiar with: JavaScript, Node, React Native, etc. However, it is only one set of tools to learn. Reusability Reusability is a big thing in software development. Whenever you are able to reuse code that is a good thing. React Native is not meant to be a write once, run everywhere platform. Whenever you want to build an app for them, you have to build a UI that looks and feels native. For this reason, some of the UI code needs to be written according to the platform's best practices and standards. However, there will always be some common UI code that can be shared together with all the logic. Being able to share code has many advantages: better use of human resources, less code to maintain, less chance of bugs, features in both platforms are more likely to be on parity, etc. Learn Once, Write Everywhere As I mentioned before, React Native is not meant to be a write once, run everywhere platform. As the Facebook team that created React Native says, the goal is to be a learn once, write everywhere platform. And this totally makes sense. Since all of the code for Android and iOS is written using the same set of tools, it is very easy to imagine having a team of developers building the app for both platforms. This is not something that will usually happen when doing native Android and iOS development because there are very few developers that do both. I can even go farther and say that a team that is developing a web app using React.js will not have a very hard time learning React Native development and start developing mobile apps. Declarative API When you build applications using React Native, your UI is more predictable and easier to understand since it has a declarative API as opposed to an imperative one. The difference between these approaches is that when you have an application that has different states, you usually need to keep track of all the changes in the UI and modify them. This can become a complex and very unpredictable task as your application grows. This is called imperative programming. If you use React Native, which has declarative APIs, you just need to worry about what the current UI state looks like without having to keep track of the older ones. Hot Reloading The usual developer routine when coding is to test changes every time some code has been written. For this to happen, the application needs to be compiled and then installed in either a simulator or a real device. In case of React Native, you don’t, most of the time, need to recompile the app every time you make a change. You just need to refresh the app in the simulator, emulator, or device and that’s it. There is even a feature called Live Reload that will refresh the app automatically every time it detects a change in the code. Isn’t that cool? Open Source React Native is still a very new technology; it was made open source less than a year ago. It is not perfect yet. It still has some bugs, but, overall, I think it is ready to be used in production for most mobile apps. There are still some features that are available in the native frameworks that have not been exposed to React Native but that is not really a big deal. I can tell from experience that it is somewhat easy to do in case you are familiar with native development. Also, since React Native is open source, there is a big community of developers helping to implement more features, fix bugs, and help people. Most of the time, if you are trying to build something that is common in mobile apps, it is very likely that it has already been built. As you can see, I am really bullish on React Native. I miss native Android and iOS development, but I really feel excited to be using React Native these days. I really think React Native is a game-changer in mobile development and I cannot wait until it becomes the to-go platform for mobile development!
Read more
  • 0
  • 0
  • 12911

article-image-rxjs-observable-promise-users-part-2
Charanjit Singh
02 Mar 2016
12 min read
Save for later

(RxJS) Observable for Promise Users : Part 2

Charanjit Singh
02 Mar 2016
12 min read
In the first post of this series we saw how RxJS Observables are similar in use to Promises and we covered how powerful they are. In this post we'll experience the power Observables bring to the table. Now, as if our little app wasn't inspirational enough, we want to overload it with inspiration. Instead of 1, we want to show 10 Chuck Norris inspirations one by one, with a delay of 2 seconds each. Let's implement that with Promises first: Promise JsBin: http://jsbin.com/wupoya/1/edit?js,output import superagent from 'superagent'; let apiUrl, inspireHTML, addPromiscuousInspiration, add10Inspirations; apiUrl = `http://api.icndb.com/jokes/random?limitTo=[nerdy,explicit]`; inspireHTML = (parentId, inspiration) => { let parentNode, inspirationalNode; parentNode = document.getElementById(parentId); inspirationalNode = document.createElement('p'); inspirationalNode.innerHTML = inspiration; parentNode.insertBefore(inspirationalNode, parentNode.firstChild); }; addPromiscuousInspiration = () => { let promiscuousInspiration; promiscuousInspiration = new Promise((resolve, reject) => { superagent .get(apiUrl) .end((err, res) => { if (err) { return reject(err); } let data, inspiration; data = JSON.parse(res.text); inspiration = data.value.joke; console.log('Inspiration has arrived!'); return resolve(inspiration); }); }); promiscuousInspiration.then((inspiration) => { let parentId; parentId = `inspiration`; inspireHTML(parentId, inspiration); }, (err) => { console.error('Error while getting inspired: ', err); }); }; add10Inspirations = () => { let maxTries, tries, interval; maxTries = 10; tries = 1; interval = setInterval(() => { addPromiscuousInspiration(); if (tries < maxTries) { tries++; } else { clearInterval(interval); } }, 2000); }; add10Inspirations(); Note: From now on we are injecting inspirations into HTML (as you'd have guessed from the code). So keep the ES6/Babel and Output panels open in JsBin Well there, we solved the problem. The code is convoluted, but it is just plain JavaScript we already know, so I am not going to explain it step-by-step. Let's try to implement the same using Observable. Observable JsBin: http://jsbin.com/wupoya/3/edit?js,output import superagent from 'superagent'; import {Observable} from 'rx'; let apiUrl, inspireHTML, reactiveInspirations; apiUrl = `http://api.icndb.com/jokes/random?limitTo=[nerdy,explicit]`; inspireHTML = (parentId, inspiration) => { let parentNode, inspirationalNode; parentNode = document.getElementById(parentId); inspirationalNode = document.createElement('p'); inspirationalNode.innerHTML = inspiration; parentNode.insertBefore(inspirationalNode, parentNode.firstChild); }; reactiveInspirations = Observable.create((observer) => { let interval, maxTries, tries; maxTries = 10; tries = 0; interval = setInterval(() => { superagent .get(apiUrl) .end((err, res) => { if (err) { return observer.onError(err); } let data, inspiration; data = JSON.parse(res.text); inspiration = data.value.joke; observer.onNext(inspiration); }); if (tries < maxTries) { tries++; } else { observer.onCompleted(); } }, 2000); return () => { console.log('Releasing the Kraken!'); clearInterval(interval); }; }); reactiveInspirations.subscribe({ onNext: (inspiration) => { let parentId; parentId = `inspiration`; inspireHTML(parentId, inspiration); }, onError: (error) => { console.error('Error while getting inspired', error); }, onCompleted: () => { console.log('Done getting inspired!'); }, }); Easter Egg: There is a tiny little easter egg in this code. Try find it if you want some candy! Hint: Observable can stop right when asked to. There are better ways of doing this (and we'll use them later), but to try comparing apples to apples I took the same approach as Promises. We'll use an interval that makes a call to the server and gets us an inspiration. You may have noticed some major differences. The consumer of our Observable (subscriber) is not changed at all, it is still assuming the same thing it was earlier. And that is a big thing. The only change we made is in the creation of our Observable. Earlier we would create a single value and called it completed, but now we set an interval and emit values making an Ajax request every 2 seconds. Take another look at how we have written the Observable creator. Notice how we are clearing the interval we set up. We put the code responsible for clearing the interval in the dispose method, because its responsibility is to release resources. And then when we have made 10 requests, we simply execute onCompleted and all the resources that need to be cleared (the interval in this case) are released. If you still can't see the power this declarative way of disposing resources brings, let's assume another case. Assume you are the consumer (subscriber) of this observable, and now you want only five inspirations. But you can't change the implementation of the Observable. How would you go about it? We can go around counting the inspirations and ignore that after we've received five, but that means we waste five requests. We want to make only five requests to the server, and then we want to stop the interval and make no more requests. We can actually do that without making a single change to how the Observable is created. When we do a reactiveInspiration.subscribe, it returns us a Disposable object. We can call reactiveInspiration.subscribe(...).dispose() any time to stop the Observable right there and release all its resources. Turns out there are many such use cases which come up more than often when you're dealing with streams/collections of asynchronous operations. RxJS provides very nice API to deal with a lot of them. Instead of manually counting the number of items emitted by our Observable and then disposing it, we can use Observable.prototype.take operator. Observable.prototype.take takes a number as input, and call dispose on the Observable after it has emitted that many values. Here we go: JsBin: http://jsbin.com/wupoya/4/edit?js,output reactiveInspirations .take(5) .subscribe({ onNext: (inspiration) => { let parentId; parentId = `inspiration`; inspireHTML(parentId, inspiration); }, onError: (error) => { console.error('Error while getting inspired', error); }, onCompleted: () => { console.log('Done getting inspired!'); }, }); If you notice in the console, you would see Releasing the Kraken! logged after five inspirations, and no more requests will be made to the server. take is one of the many operators available on the Observable that we can use to declaratively manipulate asynchronous collections. Doing the same thing in the present implementation with promises would involve making changes all over the place. Some would argue that we could create a list of promises and use a library like Q to work over it sequentially, or sequentially create a list of promises with Q and then sequentially operate on it (or something better), but that's not the point. The point is that our use case is to handle a list of asynchronous operations, and Promises are not designed for it. At the end of the day both Promise and Observable are just abstractions for same operation, the one which makes the job easier wins. Easy here is not just the "easy to implement", but easy includes: easy to think easy to implement easy to read easy to maintain easy to extend easy to reuse I don't know about you but the expected behavior of a Promise for me is that it will execute when I want it to, not when I create it. That is what I expected of it when I first tried one. I mean they advertised it as a "unit of asynchronous operation" not as a "unit of asynchronous operation which is already done, here's the dump it took on you". I won't go into explaining each point about which code stands on which of the above points, since that's your job. In my opinion Observables encourage good architecture with maintainable/modular code. From this point on we'll abandon the Promise-based implementation and build little more on Observable implementations. For starters, let's clean it up and do it the right way. import superagent from 'superagent'; import {Observable} from 'rx'; let apiUrl, inspireHTML, getInspiration; apiUrl = `http://api.icndb.com/jokes/random?limitTo=[nerdy,explicit]`; inspireHTML = (parentId, inspiration) => { let parentNode, inspirationalNode; parentNode = document.getElementById(parentId); inspirationalNode = document.createElement('p'); inspirationalNode.innerHTML = inspiration; parentNode.insertBefore(inspirationalNode, parentNode.firstChild); }; getInspiration = () => new Promise((resolve, reject) => { superagent .get(apiUrl) .end((err, res) => { if (err) { return reject(err); } let data, inspiration; data = JSON.parse(res.text); inspiration = data.value.joke; resolve(inspiration); }); }); Observable .interval(2000) .take(10) .flatMap(getInspiration) .subscribe({ onNext: (inspiration) => { let parentId; parentId = `inspiration`; inspireHTML(parentId, inspiration); }, onError: (error) => { console.error('Error while getting inspired', error); }, onCompleted: () => { console.log('Done getting inspired!'); }, }); Promises are not bad. They are designed to represent single asynchronous operations and they do their job fine. (Another) Best thing about RxJS is interoperability. They play well with almost all (a)synchronous forms, including regular arrays, promises, generators, events, and even ES7 async functions. Promises in particular are smooth to work with in RxJS, because when we return a promise in an Observable chain, it gets automatically converted to an Observable. Let's dissect that code from bottom up again. At the bottom of that code is an Observable chain. Yup, a chain! It's a chain of small independent operations that do a single task in our operation. Let's start from the top of this chain. On the top of the chain sits an Observable.interval(2000). Observable.create that we used earlier is one of many ways to create an Observable. Many times (I'd say mostly) we use special purpose operators to create Observable from promises, callbacks, events, and intervals. Observable.interval(N) creates an Observable which emits a value every N milliseconds. It just constantly keeps emitting the values indefinitely. To ask it to stop after emitting 10 values, we use Observable.prototype.take(N). take will accept N values, and then ask its parent to stop. Take, like most other operators, creates an Observable, so we can chain it further. Next in the chain we have a flatMap. If you have never worked with Array-extras like map/filter/reduce, flatMap might be hard to understand at first. Array.prototype.map takes a function, and you can apply it to each item in the array, and return a new array from returned values of the functions. There is another method not included in the default native array extras (but is provided by utility libraries like underscore/lodash/ramda) called flatten. flatten takes an array, and if that array further contains arrays, it flattens them all and returns a single dimensional array. It converts arrays like [1, 2, 3, [4, 5]] to [1, 2, 3, 4, 5, 6]. flatMap is a combination of map and flatten. It takes a function, invokes it on every item in the collection, and then flattens the resulting collection. RxJs tries to mimic the Array-extra API, which makes working with asynchronous collections so much more natural and intuitive. So you have map, filter, reduce and friends available on Observables. flatMap is also great. It flattens the Observable within the Observable to a value and passes it down the chain (i.e creates another Observable that emits flattened values, but let's not get technical). To understand it well, let's take another look at our example: .flatMap(getInspiration). getInspiration returns a Promise. As I said earlier, Promises inside the Observable chain get automatically converted to Observable. So we can safely say that getInspiration returns an Observable. If we used a simple map instead of flatMap, it would just return an Observable for each value it gets from Observable.interval, so it would give us an Observable every 2 seconds. But flatMap goes a step ahead and flattens this Observable so it will resolve this Observable, and give us its value. What value does the Promise/Observable returned by getInspiration resolve to? It resolves to the inspiration. So that's what we get in the next part of the chain. Wow! Such complex task done with such a simple API. Next in the chain is our subscriber, i.e the end of the chain. Here we expect whatever end result we wanted. Here we just do some work on it (append it in our page). I hope it wasn't too much for you to grasp. If it was, perhaps you should go ahead and take a tour of this awesome rxjs tutorial. I am sure you are as impressed by now as I am. The ability to compose asynchronous operations like this brings great power and agility to our code. Plus it is so much fun to code this way. Let's add some more features for our inspirational app. Why not remove the 10 inspiration limit and instead add a button to stop getting inspired when we feel like we're done? JsBin: http://jsbin.com/jenule/1/edit?js,output import superagent from 'superagent'; import {Observable} from 'rx'; let apiUrl, inspireHTML, getInspiration, stopButtonId, stopGettingInspired; apiUrl = `http://api.icndb.com/jokes/random?limitTo=[nerdy,explicit]`; inspireHTML = (parentId, inspiration) => { let parentNode, inspirationalNode; parentNode = document.getElementById(parentId); inspirationalNode = document.createElement('p'); inspirationalNode.innerHTML = inspiration; parentNode.insertBefore(inspirationalNode, parentNode.firstChild); }; getInspiration = () => new Promise((resolve, reject) => { superagent .get(apiUrl) .end((err, res) => { if (err) { return reject(err); } let data, inspiration; data = JSON.parse(res.text); inspiration = data.value.joke; resolve(inspiration); }); }); stopButtonId = 'stop'; stopGettingInspired = Observable .fromEvent(document.getElementById(stopButtonId), 'click') .do((event) => event.preventDefault()); Observable .interval(2000) .takeUntil(stopGettingInspired) .flatMap(getInspiration) .subscribe({ onNext: (inspiration) => { let parentId; parentId = `inspiration`; inspireHTML(parentId, inspiration); }, onError: (error) => { console.error('Error while getting inspired', error); }, onCompleted: () => { console.log('Done getting inspired!'); }, }); Let's quickly go over what new we've added: Stop Button : We've added a stop button in the HTML with HTML id stop. In our JavaScript, we created a new Observable for click events on this button. Observable.fromEvent does that for you. I won't go in much detail here (I am already way out of my allotted space), but this is really powerful. Plus I promised you I'd show you events in action). This allow us to think of click events on our button as any other asynchronous collection, which we can combine with other Observable. That's what we do. We want to stop our Observable.interval Observable on clicking the stop button. take is one of many operators for restricting an Observable. Another one is takeUntil. takeUntil works exactly like take, but instead of taking a number, it takes another Observable. When this Observable emits a value, it stops its parent Observable. So in our case, when our stopGettingInspired Observable emits a value (it emits the click event when we click the button), our interval is stopped. That's some great extensibility! That's all the fun we going to have for today. If you felt like it was too much, I'd recommend you read this tutorial again: . Or if you felt it was too simple, I wrote a small (but use-able) RSS reader as a tutorial here. About the author Charanjit Singh is a freelance developer based out of Punjab, India. He can be found on GitHub @channikhabra.
Read more
  • 0
  • 0
  • 10415
article-image-introducing-openstack-trove
Packt
02 Mar 2016
17 min read
Save for later

Introducing OpenStack Trove

Packt
02 Mar 2016
17 min read
In this article, Alok Shrivastwa and Sunil Sarat, authors of the book OpenStack Trove Essentials, explain how OpenStack Trove truly and remarkably is a treasure or collection of valuable things, especially for open source lovers like us and, of course, it is an apt name for the Database as a Service (DBaaS) component of OpenStack. In this article, we shall see why this component shows the potential and is on its way to becoming one of the crucial components in the OpenStack world. In this article, we will cover the following: DBaaS and its advantages An introduction to OpenStack's Trove project and its components Database as a Service Data is a key component in today's world, and what would applications do without data? Data is very critical, especially in the case of businesses such as the financial sector, social media, e-commerce, healthcare, and streaming media. Storing and retrieving data in a manageable way is absolutely key. Databases, as we all know, have been helping us manage data for quite some time now. Databases form an integral part of any application. Also, the data-handling needs of different type of applications are different, which has given rise to an increase in the number of database types. As the overall complexity increases, it becomes increasingly challenging and difficult for the database administrators (DBAs) to manage them. DBaaS is a cloud-based service-oriented approach to offering databases on demand for storing and managing data. DBaaS offers a flexible and scalable platform that is oriented towards self-service and easy management, particularly in terms of provisioning a business' environment using a database of choice in a matter of a few clicks and in minutes rather than waiting on it for days or even, in some cases, weeks. The fundamental building block of any DBaaS is that it will be deployed over a cloud platform, be it public (AWS, Azure, and so on) or private (VMware, OpenStack, and so on). In our case, we are looking at a private cloud running OpenStack. So, to the extent necessary, you might come across references to OpenStack and its other services, on which Trove depends. XaaS (short for Anything/Everything as a Service, of which DBaaS is one such service) is fast gaining momentum. In the cloud world, everything is offered as a service, be it infrastructure, software, or, in this case, databases. Amazon Web Services (AWS) offers various services around this: the Relational Database Service (RDS) for the RDBMS (short for relational database management system) kind of system; SimpleDB and DynamoDB for NoSQL databases; and Redshift for data warehousing needs. The OpenStack world was also not untouched by the growing demand for DBaaS, not just by users but also by DBAs, and as a result, Trove made its debut with the OpenStack release Icehouse in April 2014 and since then is one of the most popular advanced services of OpenStack. It supports several SQL and NoSQL databases and provides the full life cycle management of the databases. Advantages Now, you must be wondering why we must even consider DBaaS over traditional database management strategies. Here are a few points you might want to consider that might make it worth your time. Reduced database management costs In any organization, most of their DBAs' time is wasted in mundane tasks such as creating databases, creating instances, and so on. They are not able to concentrate on tasks such as fine-tuning SQL queries so that applications run faster, not to mention the time taken to do it all manually (or with a bunch of scripts that need to be fired manually), so this in effect is wasting resources in terms of both developers' and DBAs' time. This can be significantly reduced using a DBaaS. Faster provisioning and standardization With DBaaS, databases that are provisioned by the system will be compliant with standards as there is very little human intervention involved. This is especially helpful in the case of heavily regulated industries. As an example, let's look at members of the healthcare industry. They are bound by regulations such as HIPAA (short for Health Insurance Portability and Accountability Act of 1996), which enforces certain controls on how data is to be stored and managed. Given this scenario, DBaaS makes the database provisioning process easy and compliant as they only need to qualify the process once, and then every other database coming out of the automated provisioning system is then compliant with the standards or controls set. Easier administration Since DBaaS is cloud based, which means there will be a lot of automation, administration becomes that much more automated and easier. Some important administration tasks are backup/recovery and software upgrade/downgrade management. As an example, with most databases, we should be able to push configuration modifications within minutes to all the database instances that have been spun out by the DBaaS system. This ensures that any new standards being thought of can easily be implemented. Scaling and efficiency Scaling (up or down) becomes immensely easy, and this reduces resource hogging, which developers used as part of their planning for a rainy day, and in most cases, it never came. In the case of DBaaS, since you don't commit resources upfront and only scale up or down as and when necessary, resource utilization will be highly efficient. These are some of the advantages available to organizations that use DBaaS. Some of the concerns and roadblocks for organizations in adopting DBaaS, especially in a public cloud model, are as follows: Companies don't want to have sensitive data leave their premises. Database access and speed are key to application performance. Not being able to manage the underlying infrastructure inhibits some organizations from going to a DBaaS model. In contrast to public cloud-based DBaaS, concerns regarding data security, performance, and visibility reduce significantly in the case of private DBaaS systems such as Trove. In addition, the benefits of a cloud environment are not lost either. Trove OpenStack Trove, which was originally called Red Dwarf, is a project that was initiated by HP, and many others contributed to it later on, including Rackspace. The project was in incubation till the Havana release of OpenStack. It was formally introduced in the Icehouse release in April 2014, and its mission is to provide scalable and reliable cloud DBaaS provisioning functionality for relational and non-relational database engines. As of the Liberty release, Trove is considered as a big-tent service. Big-tent is a new approach that allows projects to enter the OpenStack code namespace. In order for a service to be a big-tent service, it only needs to follow some basic rules, which are listed here. This allows the projects to have access to the shared teams in OpenStack, such as the infrastructure teams, release management teams, and documentation teams. The project should: Align with the OpenStack mission Subject itself to the rulings of the OpenStack Technical Committee Support Keystone authentication Be completely open source and open community based At the time of writing the article, the adoption and maturity levels are as shown here: The previous diagram shows that the Age of the project is just 2 YRS and it has a 27% Adoption rate, meaning 27 of 100 people running OpenStack also run Trove. The maturity index is 1 on a scale of 1 to 5. It is derived from the following five aspects: The presence of an installation guide Whether the Adoption percentage is greater or lesser than 75 Stable branches of the project Whether it supports seven or more SDKs Corporate diversity in the team working on the project Without further ado, let's take a look at the architecture that Trove implements in order to provide DBaaS. Architecture The trove project uses some shared components and some dedicated project-related components as mentioned in the following subsections. Shared components The Trove system shares two components with the other OpenStack projects, the backend database (MySQL/MariaDB), and the message bus. The message bus The AMQP (short for Advanced Message Queuing Protocol) message bus brokers the interactions between the task manager, API, guest agent, and conductor. This component ensures that Trove can be installed and configured as a distributed system. MySQL/MariaDB MySQL or MariaDB is used by Trove to store the state of the system. API This component is responsible for providing the RESTful API with JSON and XML support. This component can be called the face of Trove to the external world since all the other components talk to Trove using this. It talks to the task manager for complex tasks, but it can also talk to the guest agent directly to perform simple tasks, such as retrieving users. The task manager The task manager is the engine responsible for doing the majority of the work. It is responsible for provisioning instances, managing the life cycle, and performing different operations. The task manager normally sends common commands, which are of an abstract nature; it is the responsibility of the guest agent to read them and issue database-specific commands in order to execute them. The guest agent The guest agent runs inside the Nova instances that are used to run the database engines. The agent listens to the messaging bus for the topic and is responsible for actually translating and executing the commands that are sent to it by the task manager component for the particular datastore. Let's also look at the different types of guest agents that are required depending on the database engine that needs to be supported. The different guest agents (for example, the MySQL and PostgreSQL guest agents) may even have different capabilities depending on what is supported on the particular database. This way, different datastores with different capabilities can be supported, and the system is kept extensible. The conductor The conductor component is responsible for updating the Trove backend database with the information that the guest agent sends regarding the instances. It eliminates the need for direct database access by all the guest agents for updating information. This is like the way the guest agent also listens to the topic on the messaging bus and performs its functions based on it. The following diagram can be used to illustrate the different components of Trove and also their interaction with the dependent services: Terminology Let's take a look at some of the terminology that Trove uses. Datastore Datastore is the term used for the RDBMS or NoSQL database that Trove can manage; it is nothing more than an abstraction of the underlying database engine, for example, MySQL, MongoDB, Percona, Couchbase, and so on. Datastore version This is linked to the datastore and defines a set of packages to be installed or already installed on an image. As an example, let's take MySQL 5.5. The datastore version will also link to a base image (operating system) that is stored in Glance. The configuration parameters that can be modified are also dependent on the datastore and the datastore version. Instance An instance is an instantiation of a datastore version. It runs on OpenStack Nova and uses Cinder for persistent storage. It has a full OS and additionally has the guest agent of Trove. Configuration group A configuration group is a bunch of options that you can set. As an example, we can create a group and associate a number of instances to one configuration group, thereby maintaining the configurations in sync. Flavor The flavor is similar to the Nova machine flavor, but it is just a definition of memory and CPU requirements for the instance that will run and host the databases. Normally, it's a good idea to have a high memory-to-CPU ratio as a flavor for running database instances. Database This is the actual database that the users consume. Several databases can run in a single Trove instance. This is where the actual users or applications connect with their database clients. The following diagram shows these different terminologies, as a quick summary. Users or applications connect to databases, which reside in instances. The instances run in Nova but are instantiations of the Datastore version belonging to a Datastore. Just to explain this a little further, say we have two versions of MySQL that are being serviced. We will have one datastore but two datastore versions, and any instantiation of that will be called an instance, and the actual MySQL database that will be used by the application will be called the database (shown as DB in the diagram). A multi-datastore scenario One of the important features of the Trove system is that it supports multiple databases to various degrees. In this subsection, we will see how Trove works with multiple Trove datastores. In the following diagram, we have represented all the components of Trove (the API, task manager, and conductor) except the Guest Agent databases as Trove Controller. The Guest Agent code is different for every datastore that needs to be supported and the Guest Agent for that particular datastore is installed on the corresponding image of the datastore version. The guest agents by default have to implement some of the basic actions for the datastore, namely, create, resize, and delete, and individual guest agents have extensions that enable them to support additional features just for that datastore. The following diagram should help us understand the command proxy function of the guest agent. Please note that the commands shown are only indicative, and the actual commands will vary. At the time of writing this article, Trove's guest agents are installable only on Linux; hence, only databases on Linux systems are supported. Feature requests (https://blueprints.launchpad.net/trove/+spec/mssql-server-db-support) were created for the ability to create a guest agent for Windows and support Microsoft SQL databases, but they have not yet been approved at the time of writing this and might be a remote possibility. Database software distribution support Trove supports various databases; the following table shows the databases supported by this service at the time of writing this. Automated installation is available for all the different databases, but there is some level of difference when it comes to the configuration capabilities of Trove with respect to different databases. This has lot to do with the lack of a common configuration base among the different databases. At the time of writing this article, MySQL and MariaDB have the most configuration options available, as shown in this list: Database Version MySQL 5.5, 5.6 Percona 5.5, 5.6 MariaDB 5.5, 10.0 Couchbase 2.2, 3.0 Cassandra 2.1 Redis 2.8 PostgreSQL 9.3, 9.4 MongoDB 2.6, 3.0 DB2 Expre 10.5 CouchDB 1.6 So, as you can see, almost all the major database applications that can run on Linux are already supported on Trove. Putting it all together Now that we have understood the architecture and terminologies, we will take a look at the general steps that are followed: Horizon/Trove CLI requests a new database instance and passes the datastore name and version, along with the flavor ID and volume size as mandatory parameters. Optional parameters such as the configuration group, AZ, replica-of, and so on can also be passed. The Trove API requests Nova for an instance with the particular image and a Cinder volume of a specific size to be added to the instance. The Nova instance boots and follows these steps: The cloud-init scripts are run(like all other Nova instances) The configuration files (for example, trove-guestagent.conf) are copied down to the instance The guest agent is installed The Trove API will also have sent the request to the task manager, which will then send the prepare call to the message bus topic. After booting, the guest agent listens to the message bus for any activities for it to do, and once it finds a message for itself, it processes the prepare command and performs the following functions: Installing the database distribution (if not already installed on the image) Creating the configuration file with the default configuration for the database engine (and any configuration from the configuration groups associated overriding the defaults) Starting the database engine and enabling auto-start Polling the database engine for availability (until the database engine is available or the timeout is reached) Reporting the status back to the Trove backend using the Trove conductor The Trove manager reports back to the API and the status of the machine is changed. Use cases So, if you are wondering all the places where we can use Trove, it fits in rather nicely with the following use cases. Dev/test databases Dev/test databases are an absolute killer feature, and almost all companies that start using Trove will definitely use it for their dev/test environments. This provides developers with the ability to freely create and dispose of database instances at will. This ability helps them be more productive and removes any lag from when they want it to when they get it. The capability of being able to take a backup, run a database, and restore the backup to another server is especially key when it comes to these kinds of workloads. Web application databases Trove is used in production for any database that supports low-risk applications, such as some web applications. With the introduction of different redundancy mechanisms, such as master-slave in MySQL, this is becoming more suited to many production environments. Features Trove is moving fast in terms of the features being added in the various releases. In this section, we will take a look at the features of three releases: the current release and the past two. The Juno release The Juno release saw a lot of features being added to the Trove system. Here is a non-exhaustive list: Support for Neutron: Now we can use both nova-network and Neutron for networking purposes Replication: MySQL master/slave replication was added. The API also allowed us to detach a slave for it to be promoted Clustering: Mongo DB cluster support was added Configuration group improvements: The functionality of using a default configuration group for a datastore version was added. This allows us to build the datastore version with a base configuration of your company standards Basic error checking was added to configuration groups The Kilo release The Kilo release majorly worked on introducing a new datastore. The following is the list of major features that were introduced: Support for the GTID (short for global transaction identifier) replication strategy New datastores, namely Vertica, DB2, and CouchDB, are supported The Liberty release The Liberty release introduced the following features to Trove. This is a non-exhaustive list. Configuration groups for Redis and MongoDB Cluster support for Redis and MongoDB Percona XtraDB cluster support Backup and restore for a single instance of MongoDB User and database management for Mongo DB Horizon support for database clusters A management API for datastores and versions The ability to deploy Trove instances in a single admin tenant so that the Nova instances are hidden from the user In order to see all the features introduced in the releases, please look at the release notes of the system, which can be found at these URLs: Juno : https://wiki.openstack.org/wiki/ReleaseNotes/Juno Kilo : https://wiki.openstack.org/wiki/ReleaseNotes/Kilo Liberty : https://wiki.openstack.org/wiki/ReleaseNotes/Liberty Summary In this article, we were introduced to the basic concepts of DBaaS and how Trove can help with this. With several changes being introduced and a score of one on five with respect to maturity, it might seem as if it is too early to adopt Trove. However, a lot of companies are giving Trove a go in their dev/test environments as well as for some web databases in production, which is why the adoption percentage is steadily on the rise. A few companies that are using Trove today are giants such as eBay, who run their dev/test Test databases on Trove; HP Helion Cloud, Rackspace Cloud, and Tesora (which is also one of the biggest contributors to the project) have DBaaS offerings based on the Trove component. Trove is increasingly being used in various companies, and it is helping in reducing DBAs' mundane work and improving standardization. Resources for Article: Further resources on this subject: OpenStack Performance, Availability [article] Concepts for OpenStack [article] Implementing OpenStack Networking and Security [article]
Read more
  • 0
  • 0
  • 3515

article-image-responsive-visualizations-using-d3js-and-bootstrap
Packt
01 Mar 2016
21 min read
Save for later

Responsive Visualizations Using D3.js and Bootstrap

Packt
01 Mar 2016
21 min read
In this article by Christoph Körner, the author of the book Learning Responsive Data Visualization, we will design and implement a responsive data visualization using Bootstrap and Media Queries based on real data. We will cover the following topics: Absolute and relative units in the browsers Drawing charts with percentage values Adapting charts using JavaScript event listeners Learning to adapt the resolution of the data Using bootstrap's Media Queries Understanding how to use Media Queries in CSS, LESS and JavaScript Learning how to use bootstrap's grid system (For more resources related to this topic, see here.) First, we will discuss the most important absolute and relative units that are available in modern browsers. You will learn the difference of absolute pixels, relative percentages, em, rem, and many more. In the next section, we will take a look at what is really needed for a chart to be responsive. Adapting the width to the parent element is one of the requirements, and you will learn about two different ways to implement this. After this section, you will know when to use percentage values or JavaScript event listeners. We will also take a look at adapting the data resolution, which is another important property of responsive visualizations. In the next section, we will explore Media Queries, and understand how we can use them to make viewport depended responsive charts. We will take the advantage of Bootstrap's definitions of Media Queries for the most common device resolutions to integrate them into our responsive chart using CSS or LESS. Finally, we will also see how to include Media Queries into JavaScript. In the last section, we will take a look at Bootstrap's grid system and learn how to seamlessly integrate it with the charts. This will give us not only some great flexibility but will also make it easier to combine multiple charts to one big dashboard application. Units and lengths in the browser Creating a responsive design, bet it website or graphics, depends strongly on the units and lengths that a browser can interpret. We can easily create an element that fills the entire width of a container using the percentage values that are relative to the parent container; whereas, achieving the same result width absolute values could be very tricky. Thus, mastering responsive graphics also means knowing all the absolute and relative units that are available in the browser. Units for Absolute lengths The most convenient and popular way in web design and development is to define and measure lengths and dimensions in absolute units, usually in pixels. The reason for this is that designers and developers often want to exactly specify the exact dimensions of an object. The pixel unit called px has been introduced as a visual unit based on a physical measurement to read from a device in the distance of approximately one arm length; however, all the modern browsers can also allow the definitions of lengths based on physical units. The following list shows the most common absolute units and their relations to each other: cm: centimeters (1 cm = 96px/2.54) mm: millimeters (1 mm = 1/10th of 1 cm) in: inches (1in = 2.54 cm = 96 px) pt: points (1 pt = 1/72th of 1 in) px: pixels (1 px = 1/96th of 1 in) More information on the origin and meaning of the pixel unit can be found in the CSS3 Specification available at http://www.w3.org/TR/css3-values/#viewport-relative-lengths. Units for Relative lengths In addition to Absolute lengths, relative lengths that are expressed as the percentage of the width or height of a parent element has also been a common technique to the style dynamic elements of web pages. Traditionally, the % unit has always been the unit of choice for the preceding reason. However, with CSS3, a couple of additional relative units have found their way into the browsers, for example, to define a length relative to the font size of the element. Here is a list of the relative length units that have been specified in the CSS3 specifications and will soon be available in modern browsers: %: the percentage of the width/height of the absolute container Em: the factor of font size of the element Rem: the factor of font size of the root element Vw: 1% of viewport's width vh: 1% viewport's height vmin: 1% of the viewport's smaller dimension (either vw or vh) vmax: 1% of the viewport's larger dimension (either vw or vh) I am aware that as a web developer, we cannot really take the advantage of any technology that will be supported soon; however, I want to point out one unit that will play an important role for feature web developers: the rem unit. The rem unit defines the length of an element based on the font size of the root node (the html node in this case), rather than the font size of the current element such as em. This rem unit is very powerful if we use it to define the lengths and spacings of a layout because the layout can also adapt when the user increases the font size of the browser (that is, for readability). I want to mention that Bootstrap 4 will replace all absolute pixel units for Media Queries by the rem units because of this reason. If we look at the following figure, we also see that rem units are already supported in all major browsers. I recommend you to start replacing all your absolute pixel units of your layout and spacing by the rem units: Cross-browser compatibility of rem units However, percentage units are not dead; we can still use them when they are appropriate. We will use them later to draw SVG elements with dimensions based on their parent elements' dimensions. Units for Resolution To round up the section of relative and absolute units, I want to mention that we can also use resolutions in different units. These resolution units can be used in Media Queries together with the min-resolution or max-resolution attribute: Dpi: dots per inch dpcm: dots per centimeter dppx: dots per px unit Mathematical Expressions We often have the problem of dealing with rational numbers or expressions in CSS; just imagine defining a 3-column grid with a width of 33% per column, or imagine the need of computing a simple expression in the CSS file. CSS3 provides a simple solution for this: calc(exp): This computes the mathematical expression called exp, which can consist of lengths, values, and the operators called +, -, /, and * Note that the + and -operators must be surrounded by whitespace. Otherwise, they will be interpreted as a sign of the second number rather than the operator. Both the other operators called * and / don't require a whitespace, but I encourage you to add them for consistency. We can use these expression in the following snippets. .col-4 { width: calc(100%/3); } .col-sp-2 { width: calc(50% - 2em); } The preceding examples look great; however, as we can see in the following figure, we need to take care of the limitations of the browser compatibility: Cross-browser compatibility of the calc() expression Responsive charts Now that we know some basics about absolute and relative units, we can start to define, design, and implement responsive charts. A responsive chart is a chart that automatically adapts its look and feel to the resolution of the user's device; thus, responsive charts need to adapt the following properties: The dimension (width and height) The resolution of data points The interactions and interaction areas. Adapting the dimensions is most obvious. The chart should always scale and adapt to the width of its parent element. In the previous section, you learned about relative and absolute lengths, so one might think that simply using relative values for the chart's dimensions would be enough. However, there are multiple ways with advantages and disadvantages to achieve this; in this section, we will discuss three of them. Adapting the resolution of the data is a little less obvious and often neglected. The resolution of data points (the amount of data point per pixel) should adapt, so that we can see more points on a device with a higher resolution and less points on a low resolution screen. In this section we will see that this can only be achieved using JavaScript event listeners and by redrawing/updating the whole chart manually. Adapting interactions and interaction areas is important for not just using different screen resolutions but also different devices. We interact differently with a TV than a computer, and we use different input devices on a desktop and mobile phone. However, the chart will allow interactions and interaction areas that are appropriate for a given device and screen resolution.. Using Relative Lengths in SVG The first and most obvious solution for adapting the dimensions of a chart to its parent container is the use of relative values for lengths and coordinates. This means that when we define the chart once with relative values and the browser takes care of recomputing all the values when the dimension of the parent container has changed, there is no manual redrawing of the chart required. First, we will add some CSS styles to scale the SVG element to the full width of the parent container: .chart { height: 16rem; position: relative; } .chart > svg { width: 100%; height: 100%; } Next, we modify all our scales to work on a range at [0, 100] and subtract a padding from both sides: var xScale = d3.scale.ordinal() .domain(flatData.map(xKey)) .rangeBands([padding, 100 - 2*padding]); var yScale = d3.scale.linear() .domain([0, d3.max(flatData, yKey)]) .range([100 - 2*padding, padding]); Finally, we can draw the chart as before, but simply adding percentage signs % at the end of the attributes—to indicate the use of percentage units: $$bars .attr('x', function(d) { return (xScale(d.x) + i*barWidth ) + '%'; }) .attr('y', function(d) { return yScale(d.y) + '%'; }) .attr('height', function(d) { return (yScale(0) - yScale(d.y)) + '%'; }) .attr('width', barWidth + '%') .attr('fill', colors(data.key)); Observe that we only slightly modified the code to plot the bars in the bar chart in order to use percentage values as coordinates for the attributes. However, the effect of this small change is enormous. In the following figure, we can see the result of the chart in a browser window: Bar chart using relative lengths If we now increase the size of the browser, the bar chart scales nicely to the full width of the parent container. We can see the scaled chart in the following figure: Scaled bar chart using relative lengths If you are not impressed by it now, you better be. This is awesome in my opinion because it leaves all the hard work of recomputing the SVG element dimensions to the browser. We don't have to care about them, and these native computations give us some maximal performance. The previous example shows how to use percentage values to create a simple bar chart. However, what we didn't explain so far is why we didn't add any axis and labels to the chart. Well, despite the idea that we can exploit native rescaling of the browser, we need to face the limitations of this technique. Relative values are only allowed in standard attributes, such as width, height, x, y, cx, cy—but not in SVG paths or transform functions. Conclusion about using Relative Lengths While this sounds like an excellent solution (and indeed it is wonderful for certain use cases), it has two major drawbacks: The percentage values are not accepted for the SVG transform attributes and for the d attribute in the path elements, only in standard attributes Due to the fact that the browser is recomputing all the values automatically, we cannot adapt the resolution of the data of the charts The first point is the biggest drawback, which means we can only position elements using the standard attributes called width, height, x, y, cx, cy, and more. However, we can still draw a bar chart that seamlessly adapts according to the parent elements without the use of JavaScript event listeners. The second argument doesn't play a huge role anymore compared to the first one, and it can be circumvented using additional JavaScript event listeners, but I am sure you get the point. Using the JavaScript Resize event The last option is to use JavaScript event handlers and redraw the chart manually when the dimensions of the parent container change. Using this technique, we can always measure the width of the parent container (in absolute units) and use this length to update and redraw the chart accordingly. This gives us great flexibility over the data resolution, and we can adapt the chart to a different aspect ratio when needed as well. The Native Resize event Theoretically, this solution sounds brilliant. We simply watch the parent container or even the SVG container itself (if it uses a width of 100%) for the resize events, and then redraw the chart when the dimensions of the element change. However, there does not exist a native resize event on the div or svg element; modern browsers only support the resize events on the window element. Hence, it triggers only if the dimensions of the browser window changes. This means also that we need to clean up listeners once we remove a chart from the page. Although this is a limitation, in most cases, we can still use the windowresize event to adapt the chart to its parent container; we have to just keep this in our mind. Let's always use the parent container's absolute dimensions for drawing and redrawing the chart; we need to define the following things inside a redraw function: var width = chart.clientWidth; var height = width / aspectRatio; Now, we can add a resize event listener to the window element and call the redraw function whenever the window dimensions change: window.addEventListener('resize', function(event){ redraw(); }); The benefit of this solution is that we can do everything that we want in the redraw function, for example, modifying the aspect ratio, adapting the labels of the axis, or modifying the number of displayed elements. The following figure shows a resized version of the previous chart; we observe that this time, the axis ticks adapt nicely and don't overlap anymore. Moreover, the axis ticks now take the full available space: Resized chart with adapted axis ticks Adapting the Resolution of the Data However, there is another problem that can be nicely solved using these types of manual redraws—the problem of data resolution. How much data should be displayed in a small chart and how much in a bigger chart? Small chart with high data resolution I think you agree that in the preceding figure, we display too much data for the size of the graphic. This is bad and makes the chart useless. Moreover, we should really adapt the resolution of the data according to the small viewport in the redrawing process. Let's implement a function that returns only ever i-th element of an array: function adaptResolution(data, resolution) { resolution = resolution ? Math.ceil(resolution) : 1; return data.filter(function(d, i) { return i % resolution === 0; }); } Great, let's define a width depended data resolution and filter the data accordingly: var pixelsPerData = 20; var resolution = pixelsPerData * (flatData.length) / width; In the previous code, we observed that we can now define the minimum amount of pixel that one data point should have and remove the amount of values accordingly by calling the following: var flatDataRes = adaptResolution(flatData, resolution); The following image shows a small chart with a low number of values, which is perfectly readable even though it is very small: Small chart with a proper data resolution In the next figure, we can see the same chart based on the same data drawn with a bigger container. We immediately observe that also the data resolutions adapts accordingly; and again, the chart looks nice: Big chart with a proper data resolution Conclusion of using Resize events This is the most flexible solution, and therefore, in many situations, it is the solution of choice. However, you need to be aware that there are also drawbacks in using this solution: There is no easy way to listen for resize events of the parent container We need to add event listeners We need to make sure that event listeners are removed properly We need to manually redraw the chart Using Bootstrap's Media Queries Bootstrap is an awesome library that gets you started quickly with new projects. It not just includes a huge amount of useful HTML components but also normalized amd standardized CSS styles. One particular style is the implementation of Media Queries for four typical device types (five types in Bootstrap 4). In this section, we will take a look at how to make use of these Media Queries in our styles and scripts. The great thing about Bootstrap is that it successfully standardizes typical device dimensions for web developers thus, beginners can simply use them without rethinking over and over which pixel width could be the most common one for tablets. Media Queries in CSS The quickest way to use Bootstrap's Media Queries is to simply copy them from the compiled source code. The queries are here: /* Extra small devices (phones, etc. less than 768px) */ /* No media query since this is the default in Bootstrap */ /* Small devices (tablets, etc.) */ @media (min-width: 768px) { ... } /* Medium devices (desktops, 992px and up) */ @media (min-width: 992px) { ... } /* Large devices (large desktops, 1200px and up) */ @media (min-width: 1200px) { ... } We can easily add these queries to our CSS styles and define certain properties and styles for our visualizations, such as four predefined widths, aspect ratios, spacing, and so on in order to adapt the chart appearance to the device type of the user. Bootstrap 4 is currently in alpha; however, I think you can already start using the predefined device types in your CSS. The reason I am strongly arguing for Bootstrap 4 is because of its shift towards the em units instead of pixels: // Extra small devices (portrait phones, etc.) // No media query since this is the default in Bootstrap // Small devices (landscape phones, etc.) @media (min-width: 34em) { ... } // Medium devices (tablets, etc.) @media (min-width: 48em) { ... } // Large devices (desktops, etc.) @media (min-width: 62em) { ... } // Extra large devices (large desktops, etc.) @media (min-width: 75em) { ... } Once again, the huge benefit of this is that the layout can adapt when the user increases the font size of the browser, for example, to enhance readability. Media Queries in LESS/SASS In Bootstrap 3, you can include Media Query mixins to your LESS file, which then gets compiled to plain CSS. To use these mixins, you have to create a LESS file instead of CSS and import the Bootstrap variables.less file. In this file, Bootstrap defines all its dimensions, colors, and other variables. Let's create a style.less file and import variables.less: // style.less @import "bower_components/bootstrap/less/variables.less"; Perfect, that's all. Now, we can go ahead and start using Bootstrap's device types in our LESS file. /* Extra small devices (phones, etc. less than 768px) */ /* No media query since this is the default in Bootstrap */ /* Small devices (tablets, etc.) */ @media (min-width: @screen-sm-min) { ... } /* Medium devices (desktops, etc.) */ @media (min-width: @screen-md-min) { ... } /* Large devices (large desktops, etc.) */ @media (min-width: @screen-lg-min) { ... } Finally, we need to use a LESS compiler to transform our style.less file to plain CSS. To achieve this, we run the following command from the terminal: lessc styles.less styles.css As we can see, the command requires the LESS compiler called lessc being installed. If it's not yet installed on your system, go ahead and install it using the following command: npm install -g less If you are new to LESS, I recommend you to read through the LESS documentation on http://lesscss.org/. Once you check out of LESS, you can also look at the very similar SASS format, which is favored by Bootstrap 4. You can find the SASS documentation at http://sass-lang.com/. We can use the Bootstrap 4 Media Queries in a SASS file by the following mixins: @include media-breakpoint-up(xs) { ... } @include media-breakpoint-up(sm) { ... } @include media-breakpoint-up(md) { ... } @include media-breakpoint-up(lg) { ... } @include media-breakpoint-up(xl) { ... } In my opinion, including Bootstrap's LESS/SASS mixins to the styles of your visualization is the cleanest solution because you always compile your CSS from the latest Bootstrap source, and you don't have to copy CSS into your project. Media Queries in JavaScript Another great possibility of using Bootstrap's Media Queries to adapt your visualization to the user's device is to use them directly in JavaScript. The native window.matchMedia (mediaQuery) function gives you the same control over your JavaScript as Media Queries gives us over CSS. Here is a little example on how to use it: if (window.matchMedia("(min-width: 1200px)").matches) { /* the viewport is at least 1200 pixels wide */ } else { /* the viewport is less than 1200 pixels wide */ } In the preceding code, we see that this function is quite easy to use and adds almost infinite customization possibilities to our visualization. More information about the matchMedia function can be found on the Mozilla Website https://developer.mozilla.org/de/docs/Web/API/Window/matchMedia. However, apart from using the watchMedia function directly, we could also use a wrapper around the native API call. I can really recommend the enquire.js library by Nick Williams, which allows you to declare event listeners for viewport changes. It can be installed via the package manager bower by running the following command from the terminal: bower install enquire Then, we need to add enquire.js to the website and use in the following snippet: enquire.register("screen and (min-width:1200px)", { // triggers when the media query matches. match : function() { /* the viewport is at least 1200 pixels wide */ }, // optional; triggers when the media query transitions unmatch : function() { /* the viewport is less than 1200 pixels wide */ }, }); In the preceding code, we see that we can now can add the match and unmatch listeners almost in the same way as listening for resize events—just much more flexible. More information about require.js can be found on the GitHub page of the project at https://github.com/WickyNilliams/enquire.js. If we would like to use the Bootstrap device types, we could easily implement them (as needed) with enquire.js and trigger events for each device type. However, I prefer being very flexible and using the bare wrapper. Using Bootstrap's Grid System Another great and quick way of making your charts responsive and play nicely together with Bootstrap is to integrate them into Bootstrap's gird system. It is the best and cleanest integration however, is to separate concerns—and make the visualization as general and adaptive as possible. Let's take our bar chart example with the custom resize events and integrate it into a simple grid layout. As usual, you can find the full source code of the example in the code examples: <div class="container"> <div class="row"> <div class="col-md-8"> <div class="chart" data-url="…" …> </div> </div> <div class="col-md-4"> <h2>My Dashboard</h2> <p>This is a simple dashboard</p> </div> </div> <div class="row"> <div class="col-md-4"> <div class="chart" data-url="…" …> </div> </div> <div class="col-md-4"> <div class="chart" data-url="…" …> </div> </div> <div class="col-md-4"> <div class="chart" data-url="…" …> </div> </div> </div> <div class="row"> <div class="col-md-6"> <div class="chart" data-url="…" …> </div> </div> <div class="col-md-6"> <div class="chart" data-url="…" …> </div> </div> </div> We observe that by making use of the parent containers' width, we can simply add the charts as the div elements in the columns of the grid. This is the preferred integration where two components play together nicely but are not depended on each other. In the following figure, we can see a screenshot from the simple dashboard that we just built. We observe that the visualizations already fit nicely into our grid layout, which makes it easy to compose them together: A simple dashboard using Bootstrap's grid layout Summary In this article, you learned the essentials about absolute and relative units to define lengths in a browser. We remember that the em and rem unit plays an important role because it allows a layout to adapt when a user increases the font size of the web site. Then, you learned about how to use relative units and JavaScript resize events to adapt the chart size and the data resolution according to the current container size. We looked into Media Queries in CSS, LESS, und JavaScript. Finally, we saw how to integrate charts with Bootstrap's grid system and implemented a simple Google Analytics-like dashboard with multiple charts.
Read more
  • 0
  • 0
  • 16457

article-image-breaking-bank
Packt
01 Mar 2016
32 min read
Save for later

Breaking the Bank

Packt
01 Mar 2016
32 min read
In this article by Jon Jenkins, author of the book Learning Xero, covers the Xero core bank functionalities, including one of the most innovative tools of our time: automated bank feeds. We will walk through how to set up the different types of bank account you may have and the most efficient way to reconcile your bank accounts. If they don't reconcile, you will be shown how you can spot and correct any errors. Automated bank feeds have revolutionized the way in which a bank reconciliation is carried out and the speed at which you can do it. Thanks to Xero, there is no longer an excuse to not keep on top of your bank accounts and therefore maintain accurate and up-to-date information for your business's key decision makers. These are the topics we'll be covering in this article: Setting up a bank feed Using rules to speed up the process Completing a bank reconciliation Dealing with common bank reconciliation errors (For more resources related to this topic, see here.) Bank overview Reconciling bank accounts has never been as easy or as quick, and we are only just at the beginning of this journey as Xero continues to push the envelope. Xero is working with banks to not only bring bank data into your accounting system but to also push it back again. That's right; you could mark a supplier invoice paid in Xero and it could actually send the payment from your bank account. Dashboard When you log in to Xero, you are presented with the dashboard, which gives a great overview of what is going on within the business. It is also an excellent place to navigate to the main parts of Xero that you will need. If you have several bank accounts, the summary pane that shows the cash in and out during a month, as shown below, is very useful as you can hover over the bar chart to get a quick snapshot of the total cash in and out for the month with no effort at all. If you want the chart to sit at the top of your dashboard, click on Edit Dashboard at the bottom of the page, and drag and drop the chart. When finished, click on Done at the bottom of the page to lock them in place. Reconciling bank accounts is fundamental to good bookkeeping, and only once the accounts have been reconciled do you know that your records are up-to-date. It isn't worth spending lots of time looking at reports if the bank accounts haven't been reconciled, as there may be important items missing from your records. By default, all bank accounts added will be shown on your dashboard, which shows the main account information, the number of unreconciled items, and the balance per Xero and per statement. You may wish to just see a few key bank accounts, in which case you can turn some of them off by going to Accounts | Bank Accounts, where you will see a list of all bank accounts. Here, you can choose to remove the bank accounts showing on the dashboard by unchecking the Show account on Dashboard option. You can also choose the Change order option, which allows you to decide the order in which you see the bank accounts on the dashboard. Click on the up and down arrows to move the accounts as required. Bank feeds If you did not set up a bank account when you were setting up Xero, then we recommend you do that now, as you cannot set up a bank feed without one. You can do this from the dashboard by clicking on the Add Bank Account button or by navigating to Accounts | Bank Accounts and Add Bank Account. Then, you are presented with of list of options including Bank Account, Credit Card, or PayPal. Enter your account details as requested and click on Save. It is very important at this stage to note that you may be presented with several options for your bank as they offer different accounts. If you choose the wrong one, your feed will not work. Some banks charge for a direct bank feed; you do not have to adhere to this, so ignore the feeds ending with Direct Bank Feed and select the alternative one. The difference between a Direct Bank Feed and the Yodlee service that Xero uses is that the data comes directly from the bank and not via a third party, so is deemed to be more reliable. Now that you have a bank account, you can add the feed by clicking on the Get bank feeds button, as shown in the following screenshot: On the Activate Bank Feed page, the fields will vary depending on the bank you use and the type of account you selected earlier. Enter the User Credentials as requested. You will then see a screen with the text Connecting to Bank, which states it might take a few minutes, so please bear with it; you are almost there. When prompted, select the bank account from the dropdown called Select the matching bank feed... that matches the account you are adding and choose whether you wish to import from a certain date or collect as much data as possible. How far it goes back varies by bank. If you are converting from another system, it would be wise to use the conversion date as the date from which you wish to start transactions, in order to avoid bringing in transactions processed in your old system (that is if your conversion date was May 31, 2015, you would use June 1, 2015. Once you are happy with the information provided, click on OK. If you have several accounts, such as a savings account, then simply follow the process again for each account. Refresh feed Each bank feed is different, and some will automatically update; others, however, require refreshing. You can usually tell which bank accounts require a manual refresh, as they will show the following message at the bottom of the bank account tile on the dashboard: To refresh the feed from the dashboard, find the account to update and click the Manage button in the top right-hand corner and then Refresh Bank Feed. You can also do this from within Accounts | Bank Accounts | Manage Accounts | Refresh Bank Feed. To update your bank feed, you will need to refresh the feed each time you want to reconcile the bank account. Import statements You get over most disappointments in life, unlike when you find out that the bank account you have does not have a bank feed available. Your options here are simple: go and change banks. But if that is too much hassle for you, then you could always just import a file. Xero accepts OFX, QIF, and CSV. Should your bank offer a selection, go with them in this order. OFX and QIF files are formatted and should import without too many problems. CSV, on the other hand, is a different matter. Each bank CSV download will come in a different format and will need some work before it is ready for importing. This takes some time, so I would recommend using the Xero Help Guide and searching Import a Bank Statement to get the file formatted correctly. If you only do things on a monthly basis, uploading a statement is not too much of a chore. We would say at this point that the automated bank feed is one of the most revolutionary things to come out of accounting software, so not using it is a crime. You simply are not enjoying the full benefits of using Xero and cloud software without it. Petty cash It probably costs the business more to find missing petty cash discrepancies than the discrepancy totals. Our advice is simple: try not to maintain a petty cash account if you can; it is just one more thing to reconcile and manage. We would advocate using a company debit card where possible, as the transactions will then go through your main bank account and you will know what is missing. Get staff to submit an expense claim, and if that is too much hassle, treat payments in and out as if they have gone through the director's loan account, as that is what happens in most small businesses. Should you wish to operate a petty cash account, you will need to mark the transactions as reconciled manually, as there is no feed to match bank payments and receipts against. In order to do this, you must first turn on the ability to mark transactions as reconciled manually. This can be found hiding in the Help section. When you click on Help, you should then see an option to Enable Mark as Reconciled, which you will need to click to turn on this functionality. Now that you have the ability to Mark as Reconciled, you can begin to reconcile the petty cash. Go to Manage | Reconcile Account. You will be presented with the four tabs below (if Cash Coding is not turned on for your user role, you will not see that tab). The Reconcile tab should be blank, as there is no feed or import in place. You will want to go to Account transactions, which is where the items you have marked as paid from petty cash will live. Underneath this section, you will also find a button called New Transactions, where you can create transactions on the fly that you may have missed or are not going to raise a sales invoice or supplier bill for. You can see from the following screenshot that we have added an example of a Spend Money transaction, but you can also create a Receive Money transaction when clicking on the New Transaction button. Click on Save when you have finished entering the details of your transaction. If you have outstanding sales invoices or purchase invoices that have been paid through the petty cash account, then you will need to mark them as paid using the petty cash bank account in order for them to appear in the Account Transactions section. To do this, navigate to those items and then complete the Make a Payment or Receive a Payment section in the bottom left-hand corner. From the main Account transactions screen, you can then mark your transactions as reconciled. Check off the items you wish to reconcile using the checkboxes on the left, then click on More | Mark as Reconciled. When you have completed the process, your bank account balance in Xero should match that of your petty cash sheet. The status of transactions marked as Reconciled Manually will change to Reconciled in black. When a transaction is reconciled, it has come in from either an import or a bank feed, and it will be green. If it is unreconciled, it will be orange. Loan account A loan account works in the same way as a bank account, and we would recommend that you set it up if a feed is available from your bank. Managing loans in Xero is easy, as you can set up a bank rule for the interest and use the Transfer facility to reconcile any loan repayments. Credit cards Like adding bank accounts, you can add credit cards from the dashboard by clicking on the Add Bank Account button or by navigating to Accounts |Bank Accounts |Add Bank Account | Credit Card. Add a card You may see several options for the bank you use, so double-check you are using the right option or the feed will not work. If there is no feed set up for your particular bank or credit card account, you will be notified as follows: In this case, you will need to either import a statement in either the OFX, QIF, or CSV format, or manually reconcile your credit card account. The process is the same as that detailed above for reconciling petty cash and will be matched against your credit card statement. If a feed is available, enter the login credentials requested to set up the feed in the same fashion as when adding a new bank account feed. Common issues Credit cards act in a different way than a bank account, in that each card is an account on its own, separate from the main account on which interest and balance payments are allocated. This means that even if you have just one business credit card, you will, in effect, have two accounts with the bank. You can add a feed for each account if you wish, but for the main account, the only transactions that will go through it are any interest accrued and balance payments to clear the card. We would suggest you set up the credit card account as a feed, as this is where you will see most transactions and therefore save the most time in processing. Each time interest is accrued, you will need to post it as a Spend Money transaction, and each time you make a payment, the amount will be a Transfer from one of your other accounts. Both these transactions will need to be marked as Reconciled Manually, as they will not appear on your credit card feed setup. This is done in the same way as oultlined in the Petty cash section earlier PayPal Just like a bank account, you can sync Xero with your PayPal account, even in multiple currencies. The ability to do this, coupled with using bank rules, can help supercharge your processing ability and cut down on posting errors. Add a feed There is a little bit of configuration required to set up a PayPal account. Go to Accounts | Bank Accounts | Add Bank Account | PayPal. Add the account name as you wish for it to appear in Xero and the currency for the account. To use the feed (why wouldn't you?), check  the Set up automatic PayPal import option, which will then bring up the other options shown in the following screenshot: As previously suggested, if converting from another system, then import transactions from the conversion dates, as with all previous transactions, should be dealt with in your old accounting system. Click on Save, and you will receive an e-mail from Xero to confirm your PayPal e-mail address. Click on the activation link in the e-mail. To complete the setup process, you need to update your PayPal settings in order for Xero to turn on the automatic feeds. In PayPal, go to My Account | Profile | My Selling Tools. Next to the API access, click on Update | Option 1. The box should then be Grant API Permission. In the Third Party Permission field, enter paypal_api1.xero.com, then click on Lookup. Under Available Permissions, make sure you check the following options: Click on Add, and you have finished the setup process. If you have multiple currency accounts, then complete this process for each currency. Bank rules Bank rules give you the ability to automate the processing of recurring payments and receipts based on your chosen criteria, and they can be a massive time saver if you have many transactions to deal with. An example would be the processing of PayPal fees on your PayPal account. Rather than having to process each one, you could set up a bank rule to deal with the transaction. Bank rules cannot be used for bank transfers or allocating supplier payment or customer receipts. Add bank rules You can add a bank rule directly from the bank statement line by clicking on Create rule above the bank line details. This means waiting for something to come through the bank first, which we think makes sense, as that detail is taken into consideration when setting up the bank rule, making it simpler to set up. You can also enter bank rules you know will need adding by going to the relevant bank account and clicking Manage Account | Bank Rules | Create Rule. We have broken the bank rule down into different sections. Section 1 allows you to set the conditions that must be present in order for the bank rule to trigger. Using equals means the payee or description in this example must match exactly. If you were to change it to contains, then only part of the description need be present. This can be very useful when the description contains a reference number that changes each month. You do not want the bank rule to fail, so you might choose to remove the reference number and change the condition to contains instead. You must set at least one condition. Section 2 allows you to set a contact, which we suggest you do; otherwise, you will have to do this on the Bank Account screen each time before being able to reconcile that bank statement line. Section 3 allows you to fix a value to an account code. This can be useful if the bank rule you are setting up contains an element of a fixed amount and variable amount. An example might be a telephone bill where the line rental is fixed and the balance is for call charges that will vary month by month. Section 4 allows you to allocate a percentage to an account code. If there is not a fixed value amount in section 3, you can just use section 4 and post 100% of the cost to the account code of your choice. Likewise, if you had a bank statement line that you wanted to split between account codes, then you could do so by entering a second line and using the percentage column. Section 5 allows you to set a reference to be used when the bank rule runs and there are five options. We would suggest not using the by me during bank rec option, as this again creates extra work, since you will have to fill it in each time before you can reconcile that bank statement line. Section 6 allows you to choose which bank account you want the bank rule to run on. This is useful if you start paying for an item out of a different bank account, as you can edit the rule and change the bank account rather than having to create the rule all over again. Section 7 allows you to set a title for the bank rule. Use something that will make it easy for you to remember when on the Bank Rules screen. Edit bank rules If your bank rules are not firing the way you expected or at all, then you will want to edit them to get them right. It is worth spending time in this area, as once you have mastered setting up bank rules, they will save you time. To edit a bank rule, you will need to navigate to Accounts | Bank Accounts | Manage Accounts | Bank Rules. Click on the bank rule you wish to edit, make the necessary adjustments, and then click on Save. You will know if the bank rule is working, as it appears like the following when reconciling your bank account. If you do not wish to apply the rule, you can click on Don't apply rule in the bottom-left corner, or if you wish to check what it is going to do, click on View details first to verify the bank rule is going to post where you prefer. Re-order bank rules The order in which your bank rules sit is the order in which Xero runs them. This is important to remember if you have bank rules set up that may conflict with each other and not return the result you were expecting. An example might be you purchasing different items from a supermarket, such as petrol and stationery. In this example, we will call it Xeroco. In most instances, the bank statement line will show two different descriptions or references, in this case Xeroco for the main store and Xeroco Fuel for the gas station. You will need to set up your rules carefully, as using only contains for Xeroco will mean that your postings could end up going to the wrong account code. You would want the Xeroco Fuel bank rule to sit above the Xeroco rule. Because they both contain the same description, if Xeroco was first, it would always trigger and everything would get posted to stationery, including the petrol. If you set Xeroco Fuel as the first bank rule to run if the bank statement line does not contain both words, it will continue and then run the Xeroco rule, which would prove successful. Gas will get posted to fuel and stationery will get posted to stationery. You can drag and drop bank rules to change the order in which they run. Hover over the two dots to the left of the bank rule number and you can drag them to the appropriate position. Bank reconciliation Bank reconciliation is one of the main drivers in knowing when your books and records are up-to-date. The introduction of automated bank feeds has revolutionized the way in which we can complete a bank reconciliation, which is the process of matching what has gone through the bank account and what has been posted in your accounting system. Below are some ways to utilize all the functionality in the Xero toolkit. Auto Suggest Xero is an intuitive system; it learns how you process transactions and is also able to make suggestions based on what you have posted. As shown below, Xero has found a match for the bank statement line on the left, which is why the right-hand panel is now green and you can see the OK button to reconcile the transaction, provided you are happy it is the correct selection. You can choose to turn Auto Suggest off. At the bottom of each page in the bank screen, you will find a checkbox, as shown in the following screenshot. Simply uncheck the Suggest previous entries box to turn it off. The more you use Xero, the better it learns, so we would advise sticking with it. It is not a substitute for checking, however, so please check before hitting the OK button. Find & Match When Xero cannot find a match and you know the bank statement line in question probably has an associated invoice or bill in the system, you can use Find & Match in the upper right-hand corner, as shown in the following screenshot: You can look through the list of unreconciled bank transactions shown in the panel or you can opt to use the Search facility and search by name, reference, or amount. In this example, you can see that we have now found two transactions from SMART Agency that total the £4,500 spent. As you can see in the following screenshot, there is also an option next to the monetary amounts that will allow you to split the transaction. This is useful if someone has not paid the invoice in full. If the amount received was only £2,500 in total, for example, you could use Split to allocate £1,000 against the first transaction and £1,500 against the second transaction. When checked off, these turn green, and you can click on OK to reconcile that bank statement line. If you cannot find a match, you will need to investigate what it relates to and if you are missing some paperwork. If we had been clever when making the original supplier payment, we could have used the Batch Payment option in Accounts |Purchases |Awaiting Payment, checking off the items that make up the amount paid, and Batch Payment would have enabled us to tell Xero that there was a payment made totaling £4,500. Auto Suggest would have picked this up, making the reconciliation easier and quicker. You have already done the hard bit by working out how much to pay suppliers; you don't want to have to do it again when an amount comes through the bank and you can't remember what it was for. It is also good practice, as it means you will not inadvertently pay the same supplier again since the bill will be marked as paid. The same can be done for customer invoices using the Deposit button. This is very helpful when receiving check deposits or remittance advice well in advance of the actual receipt. By marking the invoices as paid, you will not chase customers for money, unnecessarily causing bad feelings along the way. Create There will be occasions when you will not have a bill or invoice in Xero from which to reconcile the bank statement line. In these situations, you will need to create a transaction to clear the bank statement line. In the example below, you can see that we have entered who the contact is, what the cost relates to, and added why we spent the money. Xero will now allow us to clear the bank statement line, as the OK button is visible. We would suggest that this option be used sparingly, as you should have paperwork posted into Xero in the form of a bill or invoice to deal with the majority of your bank statement lines. Bank transfers When you receive money in or transfer money out to another bank account, you have set up within Xero a very simple way to deal with those transactions. Click on the Transfer tab and choose the bank account from the dropdown. You will then be able to reconcile that bank statement line. In the account that you have made the transfer to, you will find that Xero will make the auto suggest for you when you reconcile that bank account. Discuss and comments When you are performing the bank reconciliation, you may find that you get stuck and you genuinely do not know what to do with it. This is where the Discuss tab, shown in the following screenshot, can help: You can simply enter a note to yourself for someone else in the business or for your advisor to take a look at. Don't forget to click on Save when you are done. If someone can answer your query, they can then enter their comment in the Discuss tab and save it. Note that at present there is no notification process when you save a comment in the Discuss tab, so you are reliant on someone regularly checking it. You will see something similar to the note underneath the business name when you log in to Xero, so you can see there is a comment that needs action. Reconciliation Report This is the major tool in your armory to check whether your bank reconciles. There is no greater feeling in life than your bank account reconciling and there being no unpresented items left hanging around. To run the report from within a bank account, click on the Reconciliation Report button next to the Manage Account button. From here, you can choose which bank account you wish to run the report from, so you do not need to keep moving between the accounts, and also a date option as you will probably want to run the report to various dates, especially if you encounter a problem. On the reconciliation report, you will see the balance in Xero, which is the cashbook balance (that is what would be in the bank if all the outstanding payments and receipts posted in Xero cleared and all the bank statement lines that have come from the bank feed were processed). The outstanding payments and receipts are invoices and bills you have marked as paid in Xero but have not been matched to a bank statement line yet. You need to keep an eye on these, as older unreconciled items would normally indicate a misallocation or uncleared item. Plus Un-Reconciled Bank Statement Lines are those items that have come through on a feed but have not yet been allocated to something in Xero. This might mean that there are missing bills or sales invoices in Xero, for example. Statement Balance is the number that should match what is on your online or paper statement, whether it is a bank account, credit card, or PayPal account. If the figures do not match, then it will need investigating. In the next section, we have highlighted some of the things that may have caused the imbalance and some ideas of what to do to rectify the situation. Manual reconciliation If you are unable to set up a bank feed or import a statement, then you can still reconcile bank accounts in Xero; it just feels a bit like going back in time. To complete a manual reconciliation, you will need to follow the same process as used to process petty cash, as discussed earlier in this article. Common errors and corrections Despite all the innovation and technological advances Xero has made in this area, there are still things that can go wrong—some human, some machine. The main thing is to recognize this and know how to deal with it in the event that it happens. We have highlighted some of the more common issues and resolutions in the following subsections. Account not reconciling There is no greater feeling than when you get that big green checkmark telling you that you have reconciled all your transactions. Fantastic job done, you think! But not quite. You need to check your bank statement, credit card statement, loan statement, or PayPal statement to make sure it definitely matches as per the preceding bank reconciliation report section. The job's not done until you have completed the manual check. Duplicated statement lines With all things technology, there is a chance that things can go wrong, and every now and again, you may find that your bank feed has duplicated a line item. This is why it is so important to check the actual statement against that in Xero. It is the only way to truly know if the accounts reconcile. A direct bank feed that costs money is deemed to be more robust, and some feeds through Yodlee are better than others. It all depends on your bank, so it is worth checking with the Xero community to get some guidance from fellow Xeroes. If you are convinced that you have a duplicated bank statement line, you can choose to delete it by finding the offending item in your account and clicking on the cross in the top left-hand corner of the bank statement line. When you hover over the cross, the item will turn red. Use this sparingly and only when you know you have a duplicated line. Missing statement lines As with duplicated statement lines, there is also the possibility of a bank statement line not being synced, and this can be picked up when checking that the Xero bank account figure matches that of your online or paper bank statement. If they do not match, then we recommend using the reconciliation report and working backwards month by month and then week by week to try and isolate the date at which the bank last reconciled. Once you have narrowed it down to a week, you can then start doing it day by day until you find the date, and then check off the items in Xero against those on your bank statement until you find the missing items. If there are several missing items, we would probably suggest doing an import via OFX, QIF, or CSV, but if there are only a few, then it would probably be best to enter them manually and then mark them as reconciled so the bank will reconcile. Remove & Redo We know you are great at what you do, but everyone has an off day. If you have allocated something incorrectly, you can easily amend it. auto suggest is fantastic, but you may get carried away and just keep hitting that the OK button without paying enough attention. This is particularly problematic for businesses dealing with lots of invoices for similar amounts. If you do find that you have made an error, then you can remove the original allocation and redo it. You can do this by going to Accounts | Bank Accounts | Manage Account | Reconcile Account | Account Transactions. As you can see in the following screenshot, once you have found the offending item, you can check it off and then click on Remove & Redo. You will also find on the right-hand side a Search button, which will allow you to search for particular transactions rather than having to scroll through endless pages. If you happen to be in the actual bank transaction when you identify a problem, then you can click on Options | Remove & Redo. This will then push the transaction back in to the bank account screen to reconcile again. Note that if you Remove & Redo a manually entered bank transaction, it will not reappear in the bank account for you to reconcile, as it was never there in the first place. What you will need to do is post the payment or receipt against the correct invoice or bill, and then manually mark it as reconciled again or create another spend or receive money transaction. Manually marked as reconciled A telltale sign that someone has inadvertently caused a problem is when you look at the Account Transactions tab in the bank account and there is a sea of green and reconciled statuses, and then you spot the odd black reconciled status. This is an indication that something has been posted to that account and marked as reconciled manually. This will need investigating, as it may be genuine, such as some missing bank statement lines, or it could be that someone has made a mistake and it needs to be removed. Understanding reports If the bank account does not reconcile and it is not something obvious, then we would suggest looking at the bank statements imported into Xero to see if there are any obvious problems. Go to Accounts | Bank Accounts | Manage Account | Bank Statements. From this screen, have a look to see if there is any overlap of dates imported and then drill into the statements to check for anything that doesn't look right. If you do come across duplicated lines, you can remove them by checking off the box on the left and then clicking on the Delete button. You can see below that the bank statement line has been grayed out and has a status of Deleted next to it. If you later discover that you have made a mistake, then you can restore the bank statement line by checking off the box again but clicking on Restore this time. If you have incorrectly imported a duplicate statement or the bank feed has done so rather than deleting the transactions, you can choose to delete the entire statement. This can be achieved by clicking on the Delete Entire Statement button at the bottom-left of the Bank Statements screen: Make sure you have checked the Also delete reconciled transactions for this statement option before clicking Delete. If you are deleting the statement because it is incorrect, it only makes sense that you also clear any transactions associated with this statement to avoid further issues. Summary We have successfully added bank feeds that are now ready for automating the bank reconciliation process. In this article, we ran through the major bank functions and set up your bank feeds, exploring how to set up bank rules to make the bank reconciliation task even easier and quicker. On top of that, we also explored the possibilities of what could go wrong, but more importantly, how to identify errors and put them right. One of the biggest bookkeeping tasks you will undertake should now seem a lot easier. Resources for Article:   Further resources on this subject: Probability of R? [article] Dealing with a Mess [article] Essbase ASO (Aggregate Storage Option) [article]
Read more
  • 0
  • 0
  • 4591
article-image-analyzing-transport-layer-protocols
Packt
01 Mar 2016
13 min read
Save for later

Analyzing Transport Layer Protocols

Packt
01 Mar 2016
13 min read
In this article by Charit Mishra, the author of Mastering Wireshark, we will help the reader understand the following topics: Checking for different analysis flags in Wireshark Understanding UDP traffic Practice questions (For more resources related to this topic, see here.) How to check for different analysis flags in Wireshark The analysis of the flags present in the TCP packets is quite simple. While using Wireshark, there is an individual section that is available in the details pane for every TCP packet. Let's take a TCP packet and see how the flags are presented in the details pane, and then we will try to create a display filter corresponding to the same. Refer to the following screenshot: Now we will see what each pointer mentions: 1: The SYN packet sent from the client to the server to initiate the three-way handshake can be seen in the list pane. 2: Flags related to the same packet is set and the hex equivalent of 000000000010 is 0 x 002. 3: For the corresponding TCP packet, the SYN flag bit is set to 1. The same can be seen in the details pane. The rest of them are still 0. Now if you wish to create a display filter to see only the SYN packets you have in the trace file, then apply the filter shown in the following screenshot. As a result, you will see only the SYN packets present in your trace file, as illustrated in the following screenshot: Let's try to create one more filter to view the SYN, ACK packets only in the list pane. Perform the following steps to create the same: Open your trace file. Choose any TCP SYN, ACK packet. Note the corresponding SYN, ACK hex equivalent value for the flags set. Create your filter using the hex equivalent you have. Your filter must look something like the following screenshot. User Datagram Protocol As defined in RFC 768, User Datagram Protocol (UDP) is a connectionless protocol, which is great to transmit real-time data between the hosts and often termed as an unreliable form of communication, reason being UDP doesn't care about the delivery of packets and any lost packets are not been recovered, because the sender is never informed about the dropped or discarded packets lost during the transmission. But still many protocols such as DHCP, DNS, TFTP, SIP, and so on, rely on this only. The protocols that use UDP as a transport mechanism have to rely upon other techniques to ensure data delivery and error-checking capabilities. They are inbuilt with such features, which can provide some level of reliability during the transmission. A point not to forget is that UDP provides faster transmission of the packets and it is not concerned about the initiation of the connection or graceful termination as seen in the TCP. That's why UDP is also referred to as a transaction-oriented protocol not a message-oriented protocol like TCP. UDP header The size of a usual UDP header is 8 bytes; the data that is added with the header can be theoretically 65535 (practically 65507) bytes long. UDP header is quite small if compared to TCP header. It has just four common fields that are Source Port, Destination Port, Packet Length, and Checksum, as follows: Source Port: The port number used by the sending side to receive any replies if needed. Probably most of the time in TCP and UDP, the port number chosen to be the part of the socket is ephemeral. And on the other side of the communication, the port number comes in the category of well-known port numbers. Destination Port: This field of the header identifies the port number used by the server or the receiving side and all the data will be transmitted to this port. This port number is assigned to a particular service by IANA and definitely it is permanently assigned to the same service specifically. For example, port 53 is for DNS and cannot be assigned to any other service (it is not advisable). Packet Length: This field specifies the length of the packet starting from the header to the end of the data; the minimum length you will observe will be 8 bytes every time that is the length of the UDP header. Checksum: As discussed earlier, checksum is performed over the data that is the packet of the packet to ensure data integrity, that is, what is sent from the sender side is the same as what the receiver got. To verify this, there are a couple of checksum algorithms which come to the rescue. Sometimes, while working with UDP mostly you will see the checksum value is 0 in the packet we received, which means that the checksum is not required to be validated. How it works To understand the way UDP works, let's go ahead and analyze some of the protocols that use UDP as a delivery protocol. First, I would like to discuss DHCP and then we will see DNS traffic as well. For the analysis purpose, I have a default gateway configured at 192.168.1.1 and a client at 192.168.1.106. Using the client, I will try to generate DHCP and DNS traffic, which will be captured Wireshark and then I will try to dissect the each protocol's communication process as well as the different components utilized during the whole session. DHCP The most common and important protocol, which assigns IP addresses to devices and enables them to be network compatible is Dynamic Host Configuration Protocol (DHCP). Now, from the client, I will try to release the IP address that the client already holds, which will generate a DHCP packet and the same will be captured by the sniffer placed. Look at the following screenshot: In the list pane, we can see a DHCP release packet, which was generated implicitly by the client in order to release the current IP address (I used the dhclient –v –r command on the Linux terminal to release the IP address. But be careful while using this command; it may disconnect your machine from the network, hence making it incompatible for network communication). The client from IP 192.168.1.106 to the server at 192.168.1.1 initiated the request. The port numbers used by the client and the server in case of DHCP is permanent. That won't be changed in your case too, until it is manually configured. The DHCP server port number is 67 and DHCP client port number is 68 by default. The same you can see in the preceding screenshot (highlighted as 3). The fourth field I have highlighted is the packet length field, which specifies the length of the packet starting from the first byte until the end of data in the packet. But out of the 308 bytes, 8 bytes is the UDP header length and the rest of the 300 bytes would be the application data appended. Interestingly, if a machine is power cycled, it will request the DHCP server to allocate an IP that, as a result, will generate a couple of packets relating to the DHCP request, release, offer, and various others that will also be using UDP as a transport mechanism. I filtered the packets listed to show only the DHCP packets using the filter udp.port==67. As a result, only the DHCP packets will be listed in the list pane. TFTP Trivial File Transfer Protocol is light-weighted version of FTP, which is used for transferring between hosts. Unlike the FTP protocol, TFTP does not ask the users for any sought of credentials. TFTP uses UDP as a transport mechanism. Most commonly, TFTP is used in the LAN environments and when dealing with manageable devices like switches and routers. Network administrators do use TFTP servers to back up configuration files and to update the firmware running in those devices. And TFTP is also used by security professionals to transfer files from their system to yours in order to escalate the privileges (gaining more rights on a compromised system). I have a TFTP server running at 192.168.1.106 and a client at 192.168.1.104. There is a text file abc.txt that I've created on the server and the client will try to download the same. And our sniffer in place will capture the traffic generated. The traffic generated due to the transaction that happened between the two hosts is successfully captured and the packets corresponding to it is shown in the following screenshot: Now, let's see what each pointer mentions: 1: The transfer of the packet initiated as soon as the client requested for the file abc.txt. The request frame can be seen in the list pane. 2: As discussed, TFTP uses UDP for the transport mechanism. Relating details for the request is shown in the details pane that states that request was initiated from an ephemeral port number from the client destined to port 69 on the server (69 is a well-known port to the TFTP protocol). 3: And the request was specific to the file abc.txt that is also shown in the details pane in the TFTP protocol section. You must be wondering about the acknowledgement packets that are shared between the two hosts. As we studied, UDP is an unreliable form of communication, so why are we seeing some sort of ACK's in UDP. The reason is that the TFTP server I am using has some kind of reliability feature inbuilt into it. Even on the client side over the standard console, after initiating the request, I received quite interactive messages from the server like "the file of size 3 bytes has been transferred successfully" and various other details were listed along with the message. An interesting thing to know here is that the port 69 was involved only in the first packet, and the rest of the packets are sent and received by the acknowledging feature the server is embedded with. So, the statement that, some protocols using UDP as transport protocol has an inbuilt feature for ensuring delivery is true which we witnessed it now. Unusual UDP traffic Suppose if the resource we are looking for is not available on the server, then how the traffic will look like. Refer to the following screenshot: As seen in the preceding screenshot, the client requested for an invalid resource that the server wasn't able to locate and hence returned with an error code and a summary message File not found. The same message was shown over the standard console to the client. Sometimes, it is also possible that the server daemon is not running and the client requests for a certain resource. In such cases, the client would receive ICMP destination unreachable with error code 3. Refer to the following screenshot for the same: Now we will see what each pointer mentions: 1: Server returned with an ICMP destination unreachable message when the TFTP server daemon on not functional 2: Client received and type code error 3 3: The details regarding the request is mentioned in the reply under the UDP protocol section, which states that the request was sent to port 69 that is currently nonfunctional. 4: The requested resource is shown under the TFTP protocol section. Unusual DNS requests are also seen very often when a client initiates a request to look for name servers associated with an address. It would look similar to the following screenshot: Now, we will see what each pointer mentions: 1: As seen in the list pane, the client at 192.168.1.106 initiated a request to look for address 8.0.0.0 and received a response in the frame number 2 2: The request was sent to the default gateway that holds the DNS cache 3: The gateway responded with a No such name error There can be multiple scenarios where you will be seeing unusual traffic related to UDP. The most important one you can look for is the TFTP traffic, which might be generated because of a TFTP client in your network. It may be a malicious traffic that you would like to take a note of. Practice questions Distinguish at least five differences between TCP and UDP protocols. Capture the three-way handshake and tear down packets using your own FTP server. Explain the purpose of window scaling and checksum offloading and tell their corresponding significance in terms of TCP communications? In what way a TCP-based communication can recover from packets loss or unexpected termination? Imitate any scenarios that can generate such traffic. Create a display filter to show only TCP, FIN, and ACK packet sent to your machine from your default gateway in the list pane. What is the difference between the absolute and relative numbering system used by Wireshark in order to keep track of the packets. What is the purpose of the options field at the end of the TCP header? What kind of arguments does it contain? There is one more way through which you can create filters for viewing packet with specific flags set. Without providing the HEX equivalent, figure out what it is and how you can filter packets set with PSH flag using the same technique. Find out why the length of the data can be practically 65507 bytes while working with UDP? What kind of packets you will see in the list pane if the server daemon for TFTP is not running? Try performing zone transfer on your locally configured DNS and capture the traffic for analyses. What interesting facts did you noticed about the packets? Explain in brief. Summary TCP is a reliable form of communication that uses the processes like three-way handshake and tear down, ensuring to make the connection reliable and interactive. A lot of traffic is generated because of these packets taking part in the creation of the session between the two hosts. The TCP header is 20 bytes long that consists of various fields like source and destination port, SEQ and ACK numbers, offset, window size, flag bits, checksum, and options. The presence of various flags and header fields let the sender and receiver make sure about the delivery as well as the integrity of the data being sent. SEQ and ACK numbers are used by the TCP-based communications to keep track of how much data is being sent across between the hosts taking part. Several popular protocols like HTTP, FTP use TCP for transport mechanism, and in case of packet loss, the retransmission of the lost frames take place to ensure successful delivery. UDP is a connectionless protocol that is a nonreliable means of communication over IP; the lost and discarded packets are never recovered. UDP does provide us with faster transmission and easier creation of sessions. UDP header is 8 bytes long, which has very few fields like source and destination port, packet length, and checksum. At the end, the Application data is appended. UDP is being utilized by many protocols today, one of the most important implementation of UDP you will see while streaming live videos from the Internet. Common protocols such as DHCP, TFTP, DNS, RTP, SIP, and so on use UDP for transport mechanism and not to mention these services are some of the major services, which we deal with in our everyday life. For making the connection reliable, some of these protocols support their own version of acknowledging features that comes inbuilt into them. Resources for Article: Further resources on this subject: Wireshark: Working with Packet Streams [article] Capturing Wireshark Packets [article] Wireshark [article]
Read more
  • 0
  • 0
  • 15321

article-image-rxjs-observable-promise-users-part-1
Charanjit Singh
29 Feb 2016
12 min read
Save for later

(RxJS) Observable for Promise Users : Part 1

Charanjit Singh
29 Feb 2016
12 min read
I heard you like Promises! You should like them; they are awesome. I assume you are here because you have heard of something even more awesome and want to know more. In this small two-part post series, we'll explore RxJS Observable with hints from your existing knowledge of JavaScript Promise. We'll see how Observable can be used in places where you might be (incorrectly) using Promise now; we'll understand what an Observable is, how similar/different from Promise it is; and we'll see how Promise and Observable are actually best friends in disguise. For our journey we'll build a small app we will call "Code like Chuck Norris app." It's a ludicrously small/simple app, which will just show quotes about Chuck Norris and programming. Our real objective is to get inspired from Chuck Norris and eventually become a better coder. For that we need to get the Chuck Norris inspirational quotes. We'll do so by requesting quotes from the holy ICNDB. We'll use superagent for making requests. It's a really simple library that allows making Ajax requests from both Node.js and the browser. For starters, let's turn that console in your browser to an inspirational one. Here's our first test run: import superagent from 'superagent'; let apiUrl; apiUrl = `http://api.icndb.com/jokes/random?limitTo=[nerdy,explicit]`; superagent .get(apiUrl) .end((err, res) => { let data, inspiration; data = JSON.parse(res.text); inspiration = data.value.joke; console.log(inspiration); }); Note that we are using ES6. You can check out the live examples on jsbin: http://jsbin.com/loyemo/edit. Fear not if you see a blank page opening that link. Just click on the Edit in JsBin button on the top right, and then turn on ES6/Babel and Console tabs in jsbin. Click on the run button to see the code running. Also make sure you have http://jsbin.com/* and not https. You won't be able to make a request to ICNDB over https. The code is fairly straight-forward. We ask superagent to make a GET request to our apiUrl, and when the request finishes, superagent invokes our callback. We don't handle the error, parse the response JSON and console.log the inspiration. Now that we know how to get inspired in the console, let's turn this callback inspiration to promise based inspiration. In this post, we'll keep building our inspirational app in 2 codebases. Every part that we build, we'll build it using both Promises and Observables. This will give you a good perspective of how things are done with both approaches. Plus, we are going to create both Promise and Observable from scratch, so to get an idea of how things work under the hood, and to see the similarities and differences between the two. Promise Promises are awesome. I liked them when I first heard of them. I mean, the ability to pass around the asynchronous computations like they are variables, what more can you ask from life?Here's what our promise-based inspiration looks like (JsBin: http://jsbin.com/qolido/edit) import superagent from 'superagent'; let apiUrl, promiscuousInspiration; apiUrl = `http://api.icndb.com/jokes/random?limitTo=[nerdy,explicit]`; promiscuousInspiration = new Promise((resolve, reject) => { superagent .get(apiUrl) .end((err, res) => { if (err) { return reject(err); } let data, inspiration; data = JSON.parse(res.text); inspiration = data.value.joke; return resolve(inspiration); }); }); promiscuousInspiration .then((inspiration) => { console.log('Inspiration: ', inspiration); }, (err) => { console.error('Error while getting inspired: ', err); }); For all the power they bring, Promises are simple business. Here we're using the ES6 native Promise. For creating a new promise we pass the Promise constructor a function that receives two functions: resolve and reject. Inside this function we do our asynchronous work. We execute reject when an error happens, else we execute resolve when the asynchronous job gets its result. And then we can carry this Promise around like a variable, and work with it elsewhere in the program. To use a promise, we use its then method, which takes two callbacks for success and error. Promises can do plenty more than this, but you already know that, right? It's about time to address the elephant in the room. Let's create an Observable for the same task and see how it looks. Observable Observables are similar to Promises in that they both represent asynchronous jobs as first class things in Javascript. The similarity doesn't end here. You can in fact think of an Observable as a Promise that can resolve more than once. Or more aptly, we have the plural of Promise. We'll come to that later, for now, let's port our inspirational console to use Observable. JsBin: http://jsbin.com/foweyo/1/edit import superagent from 'superagent'; import {Observable} from 'rx'; let apiUrl, reactiveInspiration; apiUrl = `http://api.icndb.com/jokes/random?limitTo=[nerdy,explicit]`; reactiveInspiration = Observable.create((observer) => { superagent .get(apiUrl) .end((err, res) => { if (err) { return observer.onError(err); } let data, inspiration; data = JSON.parse(res.text); inspiration = data.value.joke; observer.onNext(inspiration); observer.onCompleted(); }); return () => { console.log('Release the kraken!'); }; }); reactiveInspiration.subscribe( (inspiration) => { console.log('Inspiration: ', inspiration); }, (error) => { console.error('Error while getting inspired', error); }, () => { console.log('Done getting inspired!'); } ); Observable.create is a helper for creating Observable for a specified subscribe method implementation (we'll see what that means in a minute). It looks very similar to creating a Promise but there are some differences. Let's walk over them from bottom up. reactiveInspiration.subscribe To use the value of a Promise, we use its 'then' method. For using an Observable, the equivalent is its subscribe method. First question that pops to mind is why the weird name? I mean aPromise.then makes perfect sense "when this promise resolves, then do this". As I hinted above, an Observable is not just a single value. It represents a series of values. You can think of it as a data stream to which we subscribe. Three callbacks to subscribe The second thing to note is three callbacks being passed to subscribe instead of just two. Again, two callbacks for success and error makes perfect sense, but what is that third one for? Well, Observable is not a single computation that'll succeed or fail, it is a series. Arrays have an implicit null value that marks the termination of Array, a value that tells the loop (or whatever uses the array) that, "We are done." Observables are the same as arrays in that they're a collection, or an asynchronous collection of asynchronous values, but still a collection (actually calling it an Iterable would make more sense but they're similar enough to be assumed same for this case). A collection needs to tell its consumer when it finishes. That is what third callback does. It's called onCompleted callback, and it gets invoked when the Observable is completed and will not receive any more values. In our simple example it gets completed right after receiving one value. The other two callbacks are called onNext and onError in that order. Together this trio makes a subscriber of the Observable. We can actually pass an object to the subscribe method with these three methods as keys (JsBin: http://jsbin.com/foweyo/2/edit): reactiveInspiration.subscribe({ onNext: (inspiration) => { console.log('Inspiration: ', inspiration); }, onError: (error) => { console.error('Error while getting inspired', error); }, onCompleted: () => { console.log('Done getting inspired!'); }, }); Implicitly, RxJs will create a Subscriber with the methods we provide and use default for those we don't provide, but let's not get technical about it. Now that you know what a subscriber is for an Observable, let's move up the code and see how to create an Observable from scratch with Observable.create. Observable.create, which creates an Observable from specified subscriber implementation. It's actually very simple in practice. Observable.create's callback is given an object as argument, which provides our three favorite methods: onNext, onError, and onCompleted. Just like we do with Promise, we do our asynchronous work in the callback we pass to Observable.create. We call the appropriate callback when the asynchronous job get its value or some error happens, or in the case of Observable, when we are done sending values from the Observable (i.e when the asynchronous job is finished). In our app, the first thing we do is check if the request as resulted in an error. If it does, we call the onError method of the observer we receive in the callback. When we get the value, we call observer.onNext. In our case we are only interested in one value, so we mark our Observable finished right after that by calling onCompleted of the observer. Release the Kraken? This all was quite similar to the Promise, but what is that function we are returning at the end? It's a function, which releases all the Krakens you use in your asynchronous operation. All of the resources that you need to get rid of when your Observable need to quit. In our case we don't have anything we want to get rid of, but there are times when we do. For example, if you haven't already guessed, we can represent almost any asynchronous operation in JavaScript as an Observable. That includes operations like events (yes including DOM events). The dark art of DOM-events can end up being pretty expensive if we forget to remove the event-listeners. So that's what we can release in this function. Just imagine how powerful this can end up being. We defined what resources to release right when we started using them! If you can't yet see the power it delivers, then just trust me on this one (as well). Being able to get rid of potentially expensive resources declaratively with a standard interface is very powerful. We'll taste a sip of this power in next part of this post. This function can be called the dispose function of the Observable. And the Observable can be said to be implementing the Disposable interface if you're into those things. The finishing part of the asynchronous operation is the default in case of a Promise. When a promise gets a value or when it meets an error, it is finished. An Observable differs from a Promise only in case of getting a value. The Observable doesn't finish when we invoke onNext. But for the other part (facing an error), they are the same as Promise. An Observable stops in two situations: when it receives onCompleted when it faces an error If any error occurs in the Observable, it stops right there and will not emit any more values unless explicitly asked to do so. It also calls its dispose function when an Observable finishes. So it's guaranteed that an Observable's resources will get freed whenever it finishes, naturally or by error. That's all there is you need to know to get started with Observables. A Promise represents a single asynchronous value, like a regular variable. Observables on the other hand represents a series of asynchronous values, like an array. Laziness The second noticeable difference you might need to know before we move to next part of this tutorial is that Observables are lazy while promises are not. In our example, let's write a comment in both cases whenever a value is arrived from the API. JsBin: http://jsbin.com/zavidi/1/edit import superagent from 'superagent'; let apiUrl, promiscuousInspiration; apiUrl = `http://api.icndb.com/jokes/random?limitTo=[nerdy,explicit]`; promiscuousInspiration = new Promise((resolve, reject) => { superagent .get(apiUrl) .end((err, res) => { if (err) { return reject(err); } let data, inspiration; data = JSON.parse(res.text); inspiration = data.value.joke; console.log('Inspiration has arrived!'); return resolve(inspiration); }); }); // promiscuousInspiration // .then((inspiration) => { // console.log('Inspiration: ', inspiration); // }, (err) => { // console.error('Error while getting inspired: ', err); // }); And let's do equivalent for Observable part (JsBin: http://jsbin.com/zavidi/3/edit): //in observable.js import superagent from 'superagent'; import {Observable} from 'rx'; let apiUrl, reactiveInspiration; apiUrl = `http://api.icndb.com/jokes/random?limitTo=[nerdy,explicit]`; reactiveInspiration = Observable.create((observer) => { superagent .get(apiUrl) .end((err, res) => { if (err) { return observer.onError(err); } let data, inspiration; data = JSON.parse(res.text); inspiration = data.value.joke; console.log('Inspiration has arrived!'); observer.onNext(inspiration); observer.onCompleted(); }); return () => { console.log('Release the Kraken!'); }; }); // reactiveInspiration.subscribe({ // onNext: (inspiration) => { // console.log('Inspiration: ', inspiration); // }, // onError: (error) => { // console.error('Error while getting inspired', error); // }, // onCompleted: () => { // console.log('Done getting inspired!'); // }, // }); Notice that we have commented out the part of the code that actually uses our Promise/Observable. Now if you run the app for both files, you'll notice that the promise code makes the request and invokes the code (you'll see a log in console) even though we don't really use the Promise. The Observable, however, acts as if it doesn't even exist. This is because Observables are lazy. An Observable won't execute code until it has at least one subscriber. We can deduce here that a let p = new Promise(...) actually carries the "value" of the promise which was obtained ages ago when the promise was created. On the other hand, an Observable carries the complete computation with it, which is executed on-demand. This laziness (like most other features of Observable) makes them very powerful. This also means that we can reproduce (re-execute) an Observable from itself (for example when you wanna retry on error), while to do the same for a Promise we need to have access to the code that generates the promise. Now that we understand what Observables are, we shall practice their real powers in next part of this tutorial. About the author Charanjit Singh is a freelance developer based out of Punjab, India. He can be found on GitHub @channikhabra.
Read more
  • 0
  • 0
  • 12820
Modal Close icon
Modal Close icon