Added two blogs posts:

- Announcement of 0.1.1 release
- Handling Database Migrations in Go
gh-pages
Jordan Wright 2016-01-31 14:51:03 -06:00
parent 5f02c2bf4a
commit 6768541a78
33 changed files with 2678 additions and 5 deletions

1
blog/CNAME Normal file
View File

@ -0,0 +1 @@
getgophish.com

View File

@ -1 +1 @@
#layout,.nav-list{padding:0}.brand-title,.content-subhead{text-transform:uppercase}.footer,.header,.post-share-links{text-align:center}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.pure-g [class*=pure-u],button,html,input,select,textarea{font-family:"Source Sans Pro",serif}.brand-title,.nav-item a,.post-title{font-family:Oxygen,sans-serif}a{text-decoration:none;color:#3d92c9}.brand-title a,.sidebar{color:#fff}a:focus,a:hover{text-decoration:underline}.brand-title a:hover,.post-share-links a:hover,.post-title:hover{text-decoration:none}h3{font-weight:100}.pure-img-responsive{max-width:100%;height:auto}.header{top:auto;margin:3em auto}.sidebar{background:#283F50;}.brand-tagline,.brand-title{margin:0}.brand-tagline{font-weight:300;color:#b0cadb}.nav-list{margin:0;list-style:none}.nav-item{display:inline-block;zoom:1}.nav-item a{background:0 0;border:2px solid #b0cadb;color:#fff;margin-top:1em;font-weight:700}.nav-item a:focus,.nav-item a:hover{border:2px solid #3d92c9;text-decoration:none}.post-share-links,pre{border:1px solid #ccc}.content-subhead{color:#aaa;border-bottom:1px solid #eee;padding:.4em 0;font-size:80%;font-weight:500;letter-spacing:.1em}.hugo,.post-title,pre .class,pre .css-property,pre .css-value,pre .entity.function,pre .id,pre .keyword,pre .sass,pre .storage.function,pre .vendor-prefix{font-weight:700}.content{padding:2em 1em 0}.post{padding-bottom:2em}.post-title{font-size:2em;color:#222;margin:.4em 0}.post-avatar{border-radius:50px;float:right;margin-left:1em}.post-description{font-family:"Source Sans Pro",serif;color:#333;line-height:1.35em}.post-meta{color:#999;font-size:90%;margin:5px 0}.post-category{margin:0 .1em;padding:.3em 1em;color:#fff;background:#999;font-size:80%}.post-category-design{background:#5aba59}.post-category-pure{background:#4d85d1}.post-category-yui{background:#8156a7}.post-category-javascript{background:#df2d4f}.post-images{margin:1em 0}.post-image-meta{margin-top:-3.5em;margin-left:1em;color:#fff;text-shadow:0 1px 1px #333}.footer{padding:1em 0;color:#555;font-size:80%}.footer ul li a{display:inline;padding:0}.hugo{color:#333}.footer .pure-menu a:focus,.footer .pure-menu a:hover{background:0 0}.footer li{list-style-type:none}.post-share-links{margin:15px 15px 0 0;float:left;padding:10px}.post-share-links a{color:#aaa;font-size:28px;line-height:36px;margin:0 auto;display:block;transition:all .3s ease-in}.post-share-links a:hover{color:#3d92c9}.post-share-links h4{font-family:Oxygen,sans-serif;margin:0 0 5px;color:#aaa}@media (min-width:48em){.content{padding:2em 3em 0;margin-left:25%}.header{margin:80% 2em 0;text-align:right}.sidebar{position:fixed;top:0;bottom:0}}pre{word-wrap:break-word;padding:6px 10px;line-height:19px;margin-bottom:20px}code{border:1px solid #eaeaea;margin:0 2px;padding:0 5px;font-size:12px}pre code{border:0;padding:0;margin:0;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}code,pre{font-family:Consolas,'Liberation Mono',Courier,monospace;color:#333;background:#f8f8f8;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}pre,pre code{font-size:13px}pre .comment{color:#998}pre .support{color:#0086B3}pre .tag,pre .tag-name{color:navy}pre .css-property,pre .css-value,pre .support.namespace,pre .vendor-prefix{color:#333}pre .constant.numeric,pre .hex-color,pre .keyword.unit{font-weight:400;color:#099}pre .entity.class{color:#458}pre .entity.function,pre .entity.id{color:#900}pre .attribute,pre .variable{color:teal}pre .string,pre .support.value{font-weight:400;color:#d14}pre .regexp{color:#009926}
#layout,.nav-list{padding:0}.brand-title,.content-subhead{text-transform:uppercase}.footer,.header,.post-share-links{text-align:center}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.pure-g [class*=pure-u],button,html,input,select,textarea{font-family:"Source Sans Pro",serif}.brand-title,.nav-item a,.post-title{font-family:Oxygen,sans-serif}a{text-decoration:none;color:#3d92c9}.brand-title a,.sidebar{color:#fff}a:focus,a:hover{text-decoration:underline}.brand-title a:hover,.post-share-links a:hover,.post-title:hover{text-decoration:none}h3{font-weight:100}.pure-img-responsive{max-width:100%;height:auto}.blog-image{max-width:100%;height:auto;display:block;text-align:center;border:1px solid #aaaaaa;border-radius:5px;margin:0 auto;}figcap{text-align:center;display:block;color:#999999;font-style:italic;}.header{top:auto;margin:3em auto}.sidebar{background:#283F50;}.brand-tagline,.brand-title{margin:0}.brand-tagline{font-weight:300;color:#b0cadb}.nav-list{margin:0;list-style:none}.nav-item{display:inline-block;zoom:1}.nav-item a{background:0 0;border:2px solid #b0cadb;color:#fff;margin-top:1em;font-weight:700}.nav-item a:focus,.nav-item a:hover{border:2px solid #3d92c9;text-decoration:none}.post-share-links,pre{border:1px solid #ccc}.content-subhead{color:#aaa;border-bottom:1px solid #eee;padding:.4em 0;font-size:80%;font-weight:500;letter-spacing:.1em}.hugo,.post-title,pre .class,pre .css-property,pre .css-value,pre .entity.function,pre .id,pre .keyword,pre .sass,pre .storage.function,pre .vendor-prefix{font-weight:700}.content{padding:2em 1em 0}.post{padding-bottom:2em}.post-title{font-size:2em;color:#222;margin:.4em 0}.post-avatar{border-radius:50px;float:right;margin-left:1em}.post-description{font-family:"Source Sans Pro",serif;color:#333;line-height:1.35em}.post-meta{color:#999;font-size:90%;margin:5px 0}.post-category{margin:0 .1em;padding:.3em 1em;color:#fff;background:#999;font-size:80%}.post-category-design{background:#5aba59}.post-category-pure{background:#4d85d1}.post-category-yui{background:#8156a7}.post-category-javascript{background:#df2d4f}.post-images{margin:1em 0}.post-image-meta{margin-top:-3.5em;margin-left:1em;color:#fff;text-shadow:0 1px 1px #333}.footer{padding:1em 0;color:#555;font-size:80%}.footer ul li a{display:inline;padding:0}.hugo{color:#333}.footer .pure-menu a:focus,.footer .pure-menu a:hover{background:0 0}.footer li{list-style-type:none}.post-share-links{margin:15px 15px 0 0;float:left;padding:10px}.post-share-links a{color:#aaa;font-size:28px;line-height:36px;margin:0 auto;display:block;transition:all .3s ease-in}.post-share-links a:hover{color:#3d92c9}.post-share-links h4{font-family:Oxygen,sans-serif;margin:0 0 5px;color:#aaa}@media (min-width:48em){.content{padding:2em 3em 0;margin-left:25%}.header{margin:80% 2em 0;text-align:right}.sidebar{position:fixed;top:0;bottom:0}}pre{word-wrap:break-word;padding:6px 10px;line-height:19px;margin-bottom:20px}code{border:1px solid #eaeaea;margin:0 2px;padding:0 5px;font-size:12px}pre code{border:0;padding:0;margin:0;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}code,pre{font-family:Consolas,'Liberation Mono',Courier,monospace;color:#333;background:#f8f8f8;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}pre,pre code{font-size:13px}pre .comment{color:#998}pre .support{color:#0086B3}pre .tag,pre .tag-name{color:navy}pre .css-property,pre .css-value,pre .support.namespace,pre .vendor-prefix{color:#333}pre .constant.numeric,pre .hex-color,pre .keyword.unit{font-weight:400;color:#099}pre .entity.class{color:#458}pre .entity.function,pre .entity.id{color:#900}pre .attribute,pre .variable{color:teal}pre .string,pre .support.value{font-weight:400;color:#d14}pre .regexp{color:#009926}.btn{background-color:#1abc9c;color:#ffffff;border: none;font-size: 15px;font-weight: normal;line-height: 1.4;border-radius: 4px;padding: 10px 15px;-webkit-font-smoothing: subpixel-antialiased;-webkit-transition: border .25s linear, color .25s linear, background-color .25s linear;transition: border .25s linear, color .25s linear, background-color .25s linear;}blockquote{margin-left:0px;padding-left:40px;border-left:5px solid #283F50;font-style:italic;}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -63,6 +63,253 @@
<div class="posts">
<h1 class="content-subhead">01 Feb 2016, 07:00</h1>
<section class="post">
<header class="post-header">
<a href="https://getgophish.com/blog/post/database-migrations-in-go/" class="post-title">Handling Database Migrations in Go</a>
<p class="post-meta">
</p>
</header>
<div class="post-description">
<h3 id="why-you-should-version-your-database:664f01dc60472cd080b34187311f6c6f">Why You Should Version Your Database</h3>
<blockquote>
<p>&ldquo;I got my database schema correct on the first try.&rdquo;</p>
<p>-No one ever.</p>
</blockquote>
<p>Like most big projects, gophish needed a way to automatically manage changes to our database schema. As new features were being added, we found ourselves in a situation that required us to add or modify columns and tables to store the new data.</p>
<p>In a hosted environment, this is no problem since we control the database and can make schema changes as we see fit. Gophish is different, in that it is software intentionally designed to run on the client&rsquo;s machine. This means that as we rollout updates to gophish&rsquo;s backend database, we need a way to easily update (or rollback!) changes to the database structure. A versioning system is a perfect fit, which introduces the idea of migrations.</p>
<h4 id="what-is-a-migration:664f01dc60472cd080b34187311f6c6f">What is a <em>Migration</em>?</h4>
<p>A migration is nothing more than a set of SQL commands to make changes to a database. Every migration typically has two parts: how to apply the changes you want, and how to roll them back.</p>
<p>To version control our database, we can create a folder holding multiple migration files. Each file will have an identifier so we know which migration should be applied and in which order. Then, we can store which version our database is currently at in the database itself so if we ever add migrations in the future, we can tell where we left off.</p>
<p>There are tools that can automate this process for us. We settled on a well-known database migration tool called <a href="https://bitbucket.org/liamstask/goose/"><code>goose</code></a>.</p>
<h3 id="introduction-to-goose:664f01dc60472cd080b34187311f6c6f">Introduction to <code>goose</code></h3>
<p>We chose to go with <a href="https://bitbucket.org/liamstask/goose/"><code>goose</code></a> since it seemed like a mature, fully-featured solution that would be easily integrated into our code. Goose typically works through the use of its command line tool aptly named <code>goose</code>.</p>
<p>To set things up, we first need to create the following folder structure:</p>
<pre><code>| db/
| | migrations/
| `-dbconf.yml
</code></pre>
<p>Our migrations will be stored in the <code>migrations</code> folder as a series of SQL files. Before we can create migrations, we have to specify the configuration for <code>goose</code> to use. This is found in the <code>dbconf.yml</code> file. In our case, we used the following configuration:</p>
<pre><code>production:
driver: sqlite3
open: gophish.db
dialect: sqlite3
import: github.com/mattn/go-sqlite3
</code></pre>
<p>This configuration specifies a single environment, <code>production</code>, that manages a SQLite database.</p>
<p>Now that we have created our configuration file, we can start making our migrations. Unfortunately, this is where the hurdles began.</p>
<h3 id="a-little-about-gophish:664f01dc60472cd080b34187311f6c6f">A Little About Gophish</h3>
<p>Normally, migrations are something that is considered early on in the database creation process. Unfortunately, our schema was already defined and we had clients already running gophish. So, we needed to orchestrate <code>goose</code> in such a way that we could create and apply our migrations without messing up any data that was already in the client&rsquo;s databases.</p>
<p>The first step was creating the migrations. To handle this, we first created an empty migration file using the following:</p>
<pre><code>goose -env production create 0.1.2_browser_post sql
goose: created ~\go\src\github.com\gophish\gophish\db\migrations\20160130184410_0.1.2_browser_post.sql
</code></pre>
<p>This command created a new empty SQL file in our migrations folder that looks like this:</p>
<pre><code>-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied
-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back
</code></pre>
<p>For our first migration, we decided to baseline our schema to the current version. To do this, we simply exported our existing schema using the sqlite3 tool. That gave us all of our <code>CREATE TABLE</code> statements that setup our tables and default data. We then copy/pasted those statements below the <code>-- +goose Up</code> section of the migrations.</p>
<p>The one change we made was to add <code>IF NOT EXISTS</code> to all of our table creation statements. This meant that if the client already had a database setup, this migration would be applied, but no changes would be made - exactly what we want.</p>
<p>The final step to create this migration was to add the rollback statements. Since this was creating the database, <code>DROP TABLE</code> equivalent statements worked just fine. You can see our final migration file <a href="https://raw.githubusercontent.com/gophish/gophish/master/db/migrations/20160118194630_init.sql">here</a>.</p>
<p>Now for the next hurdle. Traditionally, migrations work by creating a new migration file and running <code>goose up</code>. Then, <code>goose</code> will compare your database version with the migration files it finds. If there are migrations that need to be applied, it will apply them in order until you are at the current version.</p>
<p>While the <code>goose up</code> command can work if we control the database, there&rsquo;s simply no way that we can expect our users to install <code>goose</code> and run <code>goose up</code> every time we want to make a database change. Our goal has always been to make the lives of our users easier, so this simply wouldn&rsquo;t work. This meant that we needed to handle the migrations in our code.</p>
<p>Fortunately for us, the <code>goose</code> CLI wraps a rich library that we can use. We were able to integrate this directly into our <code>Setup()</code> function to apply migrations automatically.</p>
<p>First, we created the <code>gooose.DBConf</code> struct to hold the configuration (a programmatic copy of our <code>dbconf.yml</code> file).</p>
<pre><code class="language-golang">// Setup the goose configuration
migrateConf := &amp;goose.DBConf{
MigrationsDir: config.Conf.MigrationsPath,
Env: &quot;production&quot;,
Driver: goose.DBDriver{
Name: &quot;sqlite3&quot;,
OpenStr: config.Conf.DBPath,
Import: &quot;github.com/mattn/go-sqlite3&quot;,
Dialect: &amp;goose.Sqlite3Dialect{},
},
}
</code></pre>
<p>Next, we need to figure out the latest database version supported by our migrations. This gives us the final &ldquo;goal&rdquo; migration that we want to upgrade to. We can do this via the function <a href="https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#GetMostRecentDBVersion"><code>goose.GetMostRecentDBVersion</code></a>.</p>
<pre><code class="language-golang">// Get the latest possible migration
latest, err := goose.GetMostRecentDBVersion(migrateConf.MigrationsDir)
if err != nil {
Logger.Println(err)
return err
}
</code></pre>
<p>And finally, we need to apply our migrations. <code>Goose</code> has a function called <a href="https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#RunMigrationsOnDb"><code>goose.RunMigrationsOnDb</code></a> which expects an existing <a href="https://golang.org/pkg/database/sql/#DB"><code>sql.DB</code></a> object. Since gophish uses the ORM <a href="https://github.com/jinzhu/gorm"><code>gorm</code></a>, we already had a <code>sql.DB</code> object already initialized that we could use to send to <code>goose</code>. This was stored in the <code>db</code> variable.</p>
<pre><code class="language-golang">// Migrate up to the latest version
err = goose.RunMigrationsOnDb(migrateConf, migrateConf.MigrationsDir, latest, db.DB())
if err != nil {
Logger.Println(err)
return err
}
</code></pre>
<p>That&rsquo;s it! You can find our full <code>Setup()</code> function <a href="https://github.com/gophish/gophish/blob/master/models/models.go#L61">here.</a> To handle any additional migrations, all we need to do is run <code>goose create</code> again, add the SQL that makes up the migration, and push out the new file. The next time clients update gophish and restart the executable, the database migrations will be applied automatically!</p>
<p>If this kind of stuff is interesting to you, and you want to see a full example of a web app written in Go, check out gophish by clicking below.</p>
<a href="https://github.com/gophish/gophish" class="btn">Download gophish</a>
</div>
</section>
<h1 class="content-subhead">01 Feb 2016, 06:00</h1>
<section class="post">
<header class="post-header">
<a href="https://getgophish.com/blog/post/release-0.1.1/" class="post-title">Announcing gophish v0.1.1</a>
<p class="post-meta">
</p>
</header>
<div class="post-description">
<img src="/blog/images/gophish_purple.png" alt="" class="pure-img" >
<p><em>Tl;dr - Download the release <a href="https://github.com/gophish/gophish/releases">here</a></em></p>
<h3 id="the-wait-is-over:1cea0120cd31cba0f7863bc47631176f"><strong>The wait is over!</strong></h3>
<p>The gophish team is excited to announce our first public beta version of gophish - version 0.1.1! This blog post will be a short introduction into what gophish is, as well as some of the insanely awesome features we&rsquo;ve created.</p>
<h3 id="what-is-gophish:1cea0120cd31cba0f7863bc47631176f">What is Gophish?</h3>
<p>Gophish is a phishing framework that makes the simulation of real-world phishing attacks dead-simple. The idea behind gophish is simple make industry-grade phishing training available to <em>everyone</em>.</p>
<p>&ldquo;Available&rdquo; in this case means two things </p>
<ul>
<li><strong>Affordable</strong> Gophish is currently open-source software that is completely free for anyone to use.</li>
<li><strong>Accessible</strong> Gophish is written in the Go programming language. This has the benefit that gophish releases are compiled binaries with no dependencies. In a nutshell, this makes installation as simple as “download and run”!</li>
</ul>
<h3 id="time-for-features:1cea0120cd31cba0f7863bc47631176f">Time For Features</h3>
<p>Ok, ok, enough with the intro. The idea of a phishing simulation platform isn&rsquo;t new. Let&rsquo;s take a look at some of the features that really set gophish apart and make it awesome.</p>
<h4 id="hosted-on-prem:1cea0120cd31cba0f7863bc47631176f">Hosted On-Prem</h4>
<p>There are many commercial offerings that provide phishing simulation/training. Unfortunately, these are SaaS solutions that require you to hand over your data to someone else.</p>
<p>Gophish is different in that it is meant to be hosted in-house. This keeps you data where it belongs - with you.</p>
<h4 id="download-run:1cea0120cd31cba0f7863bc47631176f">Download -&gt; Run</h4>
<p>For the few existing in-house solutions that exist, setup can be a <em>huge pain</em> (looking at you, Ruby gems). Your time is too valuable to be spent wrestling with dependencies trying to create the perfect setup that somehow magically allows the program to run.</p>
<p>Gophish was written in the Go programming language for this exact reason. To install gophish, all you have to do is download the zip file, extract the contents, and run the binary.</p>
<p>By doing this, you just started two webservers, populated a database, and setup a background worker to handle sending the mails. Now, your time can be spent making campaigns. Easy peasy.</p>
<h4 id="api-s-for-everything:1cea0120cd31cba0f7863bc47631176f">API&rsquo;s for <em>Everything</em>.</h4>
<p>Gophish was built with automation first. This means that you can create scripts and clients that automate all the hard work for you. In addition to this, we keep up-to-date <a href="/documentation/api/">API docs</a> that describe each API endpoint in detail.</p>
<h4 id="rock-solid-documentation:1cea0120cd31cba0f7863bc47631176f">Rock-Solid Documentation</h4>
<p>Speaking of API docs, we take documentation very seriously. We take documentation seriously because we take our user experience seriously. If you can&rsquo;t find what you need to use and troubleshoot gophish, we&rsquo;ve failed. Just take a look at our comprehensive <a href="/documentation/Gophish%20User%20Guide.pdf">user guide</a>, <a href="/documentation/api/">API documentation</a>, and even <a href="http://godoc.org/github.com/gophish/gophish">fully documented code</a>.</p>
<p>If you ever find something missing in our documentation, <a href="/support">we want to know!</a></p>
<h4 id="beautiful-ui:1cea0120cd31cba0f7863bc47631176f">Beautiful UI</h4>
<p>While the API is the core of gophish&rsquo;s functionality, we also provide a gorgeous admin UI. This UI is simply a wrapper on top of the underlying API. Nothing says more than screenshots:</p>
<p><figure>
<img src="/blog/images/screenshots/login.png" alt="" class="blog-image" >
<figcap>Login Screen</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/new_group.png" alt="" class="blog-image" >
<figcap>Creating a New Group</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/new_template.png" alt="" class="blog-image" >
<figcap>Creating an Email Template</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/import_site.png" alt="" class="blog-image" >
<figcap>Importing a Site</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/campaign_results.png" alt="" class="blog-image" >
<figcap>Viewing Campaign Results</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/timeline.png" alt="" class="blog-image" >
<figcap>Viewing the Timeline for a Target</figcap>
</figure>
</p>
<h3 id="take-gophish-for-a-spin:1cea0120cd31cba0f7863bc47631176f">Take Gophish for a Spin!</h3>
<p>These features only scratch the surface when it comes to what makes gophish great, and we aren&rsquo;t anywhere near done yet. To explore these features for yourself, take gophish for a spin!</p>
<p>We hope you enjoy gophish and are excited for all the new features that will be released soon! In the meantime, if you ever have any questions, comments, or issues, <a href="/support">we want to hear from you</a>!</p>
<p>-The Gophish Team</p>
<p><a href="https://github.com/gophish/gophish/releases" class="btn">Download gophish</a>
</p>
</div>
</section>
<h1 class="content-subhead">07 Jan 2016, 22:05</h1>
<section class="post">
<header class="post-header">

View File

@ -6,9 +6,240 @@
<description>Recent content on Gophish - Blog</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<lastBuildDate>Thu, 07 Jan 2016 22:05:58 -0600</lastBuildDate>
<lastBuildDate>Mon, 01 Feb 2016 07:00:00 -0600</lastBuildDate>
<atom:link href="https://getgophish.com/blog/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>Handling Database Migrations in Go</title>
<link>https://getgophish.com/blog/post/database-migrations-in-go/</link>
<pubDate>Mon, 01 Feb 2016 07:00:00 -0600</pubDate>
<guid>https://getgophish.com/blog/post/database-migrations-in-go/</guid>
<description>
&lt;h3 id=&#34;why-you-should-version-your-database:664f01dc60472cd080b34187311f6c6f&#34;&gt;Why You Should Version Your Database&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;I got my database schema correct on the first try.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;-No one ever.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Like most big projects, gophish needed a way to automatically manage changes to our database schema. As new features were being added, we found ourselves in a situation that required us to add or modify columns and tables to store the new data.&lt;/p&gt;
&lt;p&gt;In a hosted environment, this is no problem since we control the database and can make schema changes as we see fit. Gophish is different, in that it is software intentionally designed to run on the client&amp;rsquo;s machine. This means that as we rollout updates to gophish&amp;rsquo;s backend database, we need a way to easily update (or rollback!) changes to the database structure. A versioning system is a perfect fit, which introduces the idea of migrations.&lt;/p&gt;
&lt;h4 id=&#34;what-is-a-migration:664f01dc60472cd080b34187311f6c6f&#34;&gt;What is a &lt;em&gt;Migration&lt;/em&gt;?&lt;/h4&gt;
&lt;p&gt;A migration is nothing more than a set of SQL commands to make changes to a database. Every migration typically has two parts: how to apply the changes you want, and how to roll them back.&lt;/p&gt;
&lt;p&gt;To version control our database, we can create a folder holding multiple migration files. Each file will have an identifier so we know which migration should be applied and in which order. Then, we can store which version our database is currently at in the database itself so if we ever add migrations in the future, we can tell where we left off.&lt;/p&gt;
&lt;p&gt;There are tools that can automate this process for us. We settled on a well-known database migration tool called &lt;a href=&#34;https://bitbucket.org/liamstask/goose/&#34;&gt;&lt;code&gt;goose&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;introduction-to-goose:664f01dc60472cd080b34187311f6c6f&#34;&gt;Introduction to &lt;code&gt;goose&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;We chose to go with &lt;a href=&#34;https://bitbucket.org/liamstask/goose/&#34;&gt;&lt;code&gt;goose&lt;/code&gt;&lt;/a&gt; since it seemed like a mature, fully-featured solution that would be easily integrated into our code. Goose typically works through the use of its command line tool aptly named &lt;code&gt;goose&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To set things up, we first need to create the following folder structure:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;| db/
| | migrations/
| `-dbconf.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our migrations will be stored in the &lt;code&gt;migrations&lt;/code&gt; folder as a series of SQL files. Before we can create migrations, we have to specify the configuration for &lt;code&gt;goose&lt;/code&gt; to use. This is found in the &lt;code&gt;dbconf.yml&lt;/code&gt; file. In our case, we used the following configuration:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;production:
driver: sqlite3
open: gophish.db
dialect: sqlite3
import: github.com/mattn/go-sqlite3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This configuration specifies a single environment, &lt;code&gt;production&lt;/code&gt;, that manages a SQLite database.&lt;/p&gt;
&lt;p&gt;Now that we have created our configuration file, we can start making our migrations. Unfortunately, this is where the hurdles began.&lt;/p&gt;
&lt;h3 id=&#34;a-little-about-gophish:664f01dc60472cd080b34187311f6c6f&#34;&gt;A Little About Gophish&lt;/h3&gt;
&lt;p&gt;Normally, migrations are something that is considered early on in the database creation process. Unfortunately, our schema was already defined and we had clients already running gophish. So, we needed to orchestrate &lt;code&gt;goose&lt;/code&gt; in such a way that we could create and apply our migrations without messing up any data that was already in the client&amp;rsquo;s databases.&lt;/p&gt;
&lt;p&gt;The first step was creating the migrations. To handle this, we first created an empty migration file using the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;goose -env production create 0.1.2_browser_post sql
goose: created ~\go\src\github.com\gophish\gophish\db\migrations\20160130184410_0.1.2_browser_post.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command created a new empty SQL file in our migrations folder that looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-- +goose Up
-- SQL in section &#39;Up&#39; is executed when this migration is applied
-- +goose Down
-- SQL section &#39;Down&#39; is executed when this migration is rolled back
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For our first migration, we decided to baseline our schema to the current version. To do this, we simply exported our existing schema using the sqlite3 tool. That gave us all of our &lt;code&gt;CREATE TABLE&lt;/code&gt; statements that setup our tables and default data. We then copy/pasted those statements below the &lt;code&gt;-- +goose Up&lt;/code&gt; section of the migrations.&lt;/p&gt;
&lt;p&gt;The one change we made was to add &lt;code&gt;IF NOT EXISTS&lt;/code&gt; to all of our table creation statements. This meant that if the client already had a database setup, this migration would be applied, but no changes would be made - exactly what we want.&lt;/p&gt;
&lt;p&gt;The final step to create this migration was to add the rollback statements. Since this was creating the database, &lt;code&gt;DROP TABLE&lt;/code&gt; equivalent statements worked just fine. You can see our final migration file &lt;a href=&#34;https://raw.githubusercontent.com/gophish/gophish/master/db/migrations/20160118194630_init.sql&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now for the next hurdle. Traditionally, migrations work by creating a new migration file and running &lt;code&gt;goose up&lt;/code&gt;. Then, &lt;code&gt;goose&lt;/code&gt; will compare your database version with the migration files it finds. If there are migrations that need to be applied, it will apply them in order until you are at the current version.&lt;/p&gt;
&lt;p&gt;While the &lt;code&gt;goose up&lt;/code&gt; command can work if we control the database, there&amp;rsquo;s simply no way that we can expect our users to install &lt;code&gt;goose&lt;/code&gt; and run &lt;code&gt;goose up&lt;/code&gt; every time we want to make a database change. Our goal has always been to make the lives of our users easier, so this simply wouldn&amp;rsquo;t work. This meant that we needed to handle the migrations in our code.&lt;/p&gt;
&lt;p&gt;Fortunately for us, the &lt;code&gt;goose&lt;/code&gt; CLI wraps a rich library that we can use. We were able to integrate this directly into our &lt;code&gt;Setup()&lt;/code&gt; function to apply migrations automatically.&lt;/p&gt;
&lt;p&gt;First, we created the &lt;code&gt;gooose.DBConf&lt;/code&gt; struct to hold the configuration (a programmatic copy of our &lt;code&gt;dbconf.yml&lt;/code&gt; file).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;// Setup the goose configuration
migrateConf := &amp;amp;goose.DBConf{
MigrationsDir: config.Conf.MigrationsPath,
Env: &amp;quot;production&amp;quot;,
Driver: goose.DBDriver{
Name: &amp;quot;sqlite3&amp;quot;,
OpenStr: config.Conf.DBPath,
Import: &amp;quot;github.com/mattn/go-sqlite3&amp;quot;,
Dialect: &amp;amp;goose.Sqlite3Dialect{},
},
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we need to figure out the latest database version supported by our migrations. This gives us the final &amp;ldquo;goal&amp;rdquo; migration that we want to upgrade to. We can do this via the function &lt;a href=&#34;https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#GetMostRecentDBVersion&#34;&gt;&lt;code&gt;goose.GetMostRecentDBVersion&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;// Get the latest possible migration
latest, err := goose.GetMostRecentDBVersion(migrateConf.MigrationsDir)
if err != nil {
Logger.Println(err)
return err
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally, we need to apply our migrations. &lt;code&gt;Goose&lt;/code&gt; has a function called &lt;a href=&#34;https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#RunMigrationsOnDb&#34;&gt;&lt;code&gt;goose.RunMigrationsOnDb&lt;/code&gt;&lt;/a&gt; which expects an existing &lt;a href=&#34;https://golang.org/pkg/database/sql/#DB&#34;&gt;&lt;code&gt;sql.DB&lt;/code&gt;&lt;/a&gt; object. Since gophish uses the ORM &lt;a href=&#34;https://github.com/jinzhu/gorm&#34;&gt;&lt;code&gt;gorm&lt;/code&gt;&lt;/a&gt;, we already had a &lt;code&gt;sql.DB&lt;/code&gt; object already initialized that we could use to send to &lt;code&gt;goose&lt;/code&gt;. This was stored in the &lt;code&gt;db&lt;/code&gt; variable.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;// Migrate up to the latest version
err = goose.RunMigrationsOnDb(migrateConf, migrateConf.MigrationsDir, latest, db.DB())
if err != nil {
Logger.Println(err)
return err
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;rsquo;s it! You can find our full &lt;code&gt;Setup()&lt;/code&gt; function &lt;a href=&#34;https://github.com/gophish/gophish/blob/master/models/models.go#L61&#34;&gt;here.&lt;/a&gt; To handle any additional migrations, all we need to do is run &lt;code&gt;goose create&lt;/code&gt; again, add the SQL that makes up the migration, and push out the new file. The next time clients update gophish and restart the executable, the database migrations will be applied automatically!&lt;/p&gt;
&lt;p&gt;If this kind of stuff is interesting to you, and you want to see a full example of a web app written in Go, check out gophish by clicking below.&lt;/p&gt;
&lt;a href=&#34;https://github.com/gophish/gophish&#34; class=&#34;btn&#34;&gt;Download gophish&lt;/a&gt;
</description>
</item>
<item>
<title>Announcing gophish v0.1.1</title>
<link>https://getgophish.com/blog/post/release-0.1.1/</link>
<pubDate>Mon, 01 Feb 2016 06:00:00 -0600</pubDate>
<guid>https://getgophish.com/blog/post/release-0.1.1/</guid>
<description>
&lt;img src=&#34;https://getgophish.com/blog/blog/images/gophish_purple.png&#34; alt=&#34;&#34; class=&#34;pure-img&#34; &gt;
&lt;p&gt;&lt;em&gt;Tl;dr - Download the release &lt;a href=&#34;https://github.com/gophish/gophish/releases&#34;&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;the-wait-is-over:1cea0120cd31cba0f7863bc47631176f&#34;&gt;&lt;strong&gt;The wait is over!&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The gophish team is excited to announce our first public beta version of gophish - version 0.1.1! This blog post will be a short introduction into what gophish is, as well as some of the insanely awesome features we&amp;rsquo;ve created.&lt;/p&gt;
&lt;h3 id=&#34;what-is-gophish:1cea0120cd31cba0f7863bc47631176f&#34;&gt;What is Gophish?&lt;/h3&gt;
&lt;p&gt;Gophish is a phishing framework that makes the simulation of real-world phishing attacks dead-simple. The idea behind gophish is simple make industry-grade phishing training available to &lt;em&gt;everyone&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Available&amp;rdquo; in this case means two things &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Affordable&lt;/strong&gt; Gophish is currently open-source software that is completely free for anyone to use.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accessible&lt;/strong&gt; Gophish is written in the Go programming language. This has the benefit that gophish releases are compiled binaries with no dependencies. In a nutshell, this makes installation as simple as “download and run”!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;time-for-features:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Time For Features&lt;/h3&gt;
&lt;p&gt;Ok, ok, enough with the intro. The idea of a phishing simulation platform isn&amp;rsquo;t new. Let&amp;rsquo;s take a look at some of the features that really set gophish apart and make it awesome.&lt;/p&gt;
&lt;h4 id=&#34;hosted-on-prem:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Hosted On-Prem&lt;/h4&gt;
&lt;p&gt;There are many commercial offerings that provide phishing simulation/training. Unfortunately, these are SaaS solutions that require you to hand over your data to someone else.&lt;/p&gt;
&lt;p&gt;Gophish is different in that it is meant to be hosted in-house. This keeps you data where it belongs - with you.&lt;/p&gt;
&lt;h4 id=&#34;download-run:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Download -&amp;gt; Run&lt;/h4&gt;
&lt;p&gt;For the few existing in-house solutions that exist, setup can be a &lt;em&gt;huge pain&lt;/em&gt; (looking at you, Ruby gems). Your time is too valuable to be spent wrestling with dependencies trying to create the perfect setup that somehow magically allows the program to run.&lt;/p&gt;
&lt;p&gt;Gophish was written in the Go programming language for this exact reason. To install gophish, all you have to do is download the zip file, extract the contents, and run the binary.&lt;/p&gt;
&lt;p&gt;By doing this, you just started two webservers, populated a database, and setup a background worker to handle sending the mails. Now, your time can be spent making campaigns. Easy peasy.&lt;/p&gt;
&lt;h4 id=&#34;api-s-for-everything:1cea0120cd31cba0f7863bc47631176f&#34;&gt;API&amp;rsquo;s for &lt;em&gt;Everything&lt;/em&gt;.&lt;/h4&gt;
&lt;p&gt;Gophish was built with automation first. This means that you can create scripts and clients that automate all the hard work for you. In addition to this, we keep up-to-date &lt;a href=&#34;https://getgophish.com/blog/documentation/api/&#34;&gt;API docs&lt;/a&gt; that describe each API endpoint in detail.&lt;/p&gt;
&lt;h4 id=&#34;rock-solid-documentation:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Rock-Solid Documentation&lt;/h4&gt;
&lt;p&gt;Speaking of API docs, we take documentation very seriously. We take documentation seriously because we take our user experience seriously. If you can&amp;rsquo;t find what you need to use and troubleshoot gophish, we&amp;rsquo;ve failed. Just take a look at our comprehensive &lt;a href=&#34;https://getgophish.com/blog/documentation/Gophish%20User%20Guide.pdf&#34;&gt;user guide&lt;/a&gt;, &lt;a href=&#34;https://getgophish.com/blog/documentation/api/&#34;&gt;API documentation&lt;/a&gt;, and even &lt;a href=&#34;http://godoc.org/github.com/gophish/gophish&#34;&gt;fully documented code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you ever find something missing in our documentation, &lt;a href=&#34;https://getgophish.com/blog/support&#34;&gt;we want to know!&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&#34;beautiful-ui:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Beautiful UI&lt;/h4&gt;
&lt;p&gt;While the API is the core of gophish&amp;rsquo;s functionality, we also provide a gorgeous admin UI. This UI is simply a wrapper on top of the underlying API. Nothing says more than screenshots:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/login.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Login Screen&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/new_group.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Creating a New Group&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/new_template.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Creating an Email Template&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/import_site.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Importing a Site&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/campaign_results.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Viewing Campaign Results&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/timeline.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Viewing the Timeline for a Target&lt;/figcap&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id=&#34;take-gophish-for-a-spin:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Take Gophish for a Spin!&lt;/h3&gt;
&lt;p&gt;These features only scratch the surface when it comes to what makes gophish great, and we aren&amp;rsquo;t anywhere near done yet. To explore these features for yourself, take gophish for a spin!&lt;/p&gt;
&lt;p&gt;We hope you enjoy gophish and are excited for all the new features that will be released soon! In the meantime, if you ever have any questions, comments, or issues, &lt;a href=&#34;https://getgophish.com/blog/support&#34;&gt;we want to hear from you&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;-The Gophish Team&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/gophish/gophish/releases&#34; class=&#34;btn&#34;&gt;Download gophish&lt;/a&gt;
&lt;/p&gt;
</description>
</item>
<item>
<title>Introducing gophish</title>
<link>https://getgophish.com/blog/post/hello-world/</link>

View File

@ -0,0 +1,227 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Handling Database Migrations in Go &middot; Gophish - Blog</title>
<meta name="description" content="">
<meta name="generator" content="Hugo 0.15" />
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Handling Database Migrations in Go &middot; Gophish - Blog">
<meta name="twitter:description" content="">
<meta property="og:type" content="article">
<meta property="og:title" content="Handling Database Migrations in Go &middot; Gophish - Blog">
<meta property="og:description" content="">
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700|Oxygen:400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/pure-min.css">
<!--[if lte IE 8]>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/grids-responsive-old-ie-min.css">
<![endif]-->
<!--[if gt IE 8]><!-->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/grids-responsive-min.css">
<!--<![endif]-->
<link rel="stylesheet" href="https://getgophish.com/blog/css/all.min.css">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="alternate" type="application/rss+xml" title="Gophish - Blog" href="https://getgophish.com/blog/index.xml" />
</head>
<body>
<div id="layout" class="pure-g">
<div class="sidebar pure-u-1 pure-u-md-1-4">
<div class="header">
<hgroup>
<h1 class="brand-title"><a href="https://getgophish.com/blog">Gophish - Blog</a></h1>
<h2 class="brand-tagline"></h2>
</hgroup>
<nav class="nav">
<ul class="nav-list">
<li class="nav-item">
<a class="pure-button" href="http://getgophish.com"><i class="fa fa-home"></i> home</a>
</li>
<li class="nav-item">
<a class="pure-button" href="https://getgophish.com/blog/index.xml"><i class="fa fa-rss"></i> rss</a>
</li>
</ul>
</nav>
</div>
</div>
<div class="content pure-u-1 pure-u-md-3-4">
<div>
<div class="posts">
<h1 class="content-subhead">01 Feb 2016, 07:00</h1>
<section class="post">
<header class="post-header">
<a href="https://getgophish.com/blog/post/database-migrations-in-go/" class="post-title">Handling Database Migrations in Go</a>
<p class="post-meta">
</p>
</header>
<div class="post-description">
<h3 id="why-you-should-version-your-database:664f01dc60472cd080b34187311f6c6f">Why You Should Version Your Database</h3>
<blockquote>
<p>&ldquo;I got my database schema correct on the first try.&rdquo;</p>
<p>-No one ever.</p>
</blockquote>
<p>Like most big projects, gophish needed a way to automatically manage changes to our database schema. As new features were being added, we found ourselves in a situation that required us to add or modify columns and tables to store the new data.</p>
<p>In a hosted environment, this is no problem since we control the database and can make schema changes as we see fit. Gophish is different, in that it is software intentionally designed to run on the client&rsquo;s machine. This means that as we rollout updates to gophish&rsquo;s backend database, we need a way to easily update (or rollback!) changes to the database structure. A versioning system is a perfect fit, which introduces the idea of migrations.</p>
<h4 id="what-is-a-migration:664f01dc60472cd080b34187311f6c6f">What is a <em>Migration</em>?</h4>
<p>A migration is nothing more than a set of SQL commands to make changes to a database. Every migration typically has two parts: how to apply the changes you want, and how to roll them back.</p>
<p>To version control our database, we can create a folder holding multiple migration files. Each file will have an identifier so we know which migration should be applied and in which order. Then, we can store which version our database is currently at in the database itself so if we ever add migrations in the future, we can tell where we left off.</p>
<p>There are tools that can automate this process for us. We settled on a well-known database migration tool called <a href="https://bitbucket.org/liamstask/goose/"><code>goose</code></a>.</p>
<h3 id="introduction-to-goose:664f01dc60472cd080b34187311f6c6f">Introduction to <code>goose</code></h3>
<p>We chose to go with <a href="https://bitbucket.org/liamstask/goose/"><code>goose</code></a> since it seemed like a mature, fully-featured solution that would be easily integrated into our code. Goose typically works through the use of its command line tool aptly named <code>goose</code>.</p>
<p>To set things up, we first need to create the following folder structure:</p>
<pre><code>| db/
| | migrations/
| `-dbconf.yml
</code></pre>
<p>Our migrations will be stored in the <code>migrations</code> folder as a series of SQL files. Before we can create migrations, we have to specify the configuration for <code>goose</code> to use. This is found in the <code>dbconf.yml</code> file. In our case, we used the following configuration:</p>
<pre><code>production:
driver: sqlite3
open: gophish.db
dialect: sqlite3
import: github.com/mattn/go-sqlite3
</code></pre>
<p>This configuration specifies a single environment, <code>production</code>, that manages a SQLite database.</p>
<p>Now that we have created our configuration file, we can start making our migrations. Unfortunately, this is where the hurdles began.</p>
<h3 id="a-little-about-gophish:664f01dc60472cd080b34187311f6c6f">A Little About Gophish</h3>
<p>Normally, migrations are something that is considered early on in the database creation process. Unfortunately, our schema was already defined and we had clients already running gophish. So, we needed to orchestrate <code>goose</code> in such a way that we could create and apply our migrations without messing up any data that was already in the client&rsquo;s databases.</p>
<p>The first step was creating the migrations. To handle this, we first created an empty migration file using the following:</p>
<pre><code>goose -env production create 0.1.2_browser_post sql
goose: created ~\go\src\github.com\gophish\gophish\db\migrations\20160130184410_0.1.2_browser_post.sql
</code></pre>
<p>This command created a new empty SQL file in our migrations folder that looks like this:</p>
<pre><code>-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied
-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back
</code></pre>
<p>For our first migration, we decided to baseline our schema to the current version. To do this, we simply exported our existing schema using the sqlite3 tool. That gave us all of our <code>CREATE TABLE</code> statements that setup our tables and default data. We then copy/pasted those statements below the <code>-- +goose Up</code> section of the migrations.</p>
<p>The one change we made was to add <code>IF NOT EXISTS</code> to all of our table creation statements. This meant that if the client already had a database setup, this migration would be applied, but no changes would be made - exactly what we want.</p>
<p>The final step to create this migration was to add the rollback statements. Since this was creating the database, <code>DROP TABLE</code> equivalent statements worked just fine. You can see our final migration file <a href="https://raw.githubusercontent.com/gophish/gophish/master/db/migrations/20160118194630_init.sql">here</a>.</p>
<p>Now for the next hurdle. Traditionally, migrations work by creating a new migration file and running <code>goose up</code>. Then, <code>goose</code> will compare your database version with the migration files it finds. If there are migrations that need to be applied, it will apply them in order until you are at the current version.</p>
<p>While the <code>goose up</code> command can work if we control the database, there&rsquo;s simply no way that we can expect our users to install <code>goose</code> and run <code>goose up</code> every time we want to make a database change. Our goal has always been to make the lives of our users easier, so this simply wouldn&rsquo;t work. This meant that we needed to handle the migrations in our code.</p>
<p>Fortunately for us, the <code>goose</code> CLI wraps a rich library that we can use. We were able to integrate this directly into our <code>Setup()</code> function to apply migrations automatically.</p>
<p>First, we created the <code>gooose.DBConf</code> struct to hold the configuration (a programmatic copy of our <code>dbconf.yml</code> file).</p>
<pre><code class="language-golang">// Setup the goose configuration
migrateConf := &amp;goose.DBConf{
MigrationsDir: config.Conf.MigrationsPath,
Env: &quot;production&quot;,
Driver: goose.DBDriver{
Name: &quot;sqlite3&quot;,
OpenStr: config.Conf.DBPath,
Import: &quot;github.com/mattn/go-sqlite3&quot;,
Dialect: &amp;goose.Sqlite3Dialect{},
},
}
</code></pre>
<p>Next, we need to figure out the latest database version supported by our migrations. This gives us the final &ldquo;goal&rdquo; migration that we want to upgrade to. We can do this via the function <a href="https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#GetMostRecentDBVersion"><code>goose.GetMostRecentDBVersion</code></a>.</p>
<pre><code class="language-golang">// Get the latest possible migration
latest, err := goose.GetMostRecentDBVersion(migrateConf.MigrationsDir)
if err != nil {
Logger.Println(err)
return err
}
</code></pre>
<p>And finally, we need to apply our migrations. <code>Goose</code> has a function called <a href="https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#RunMigrationsOnDb"><code>goose.RunMigrationsOnDb</code></a> which expects an existing <a href="https://golang.org/pkg/database/sql/#DB"><code>sql.DB</code></a> object. Since gophish uses the ORM <a href="https://github.com/jinzhu/gorm"><code>gorm</code></a>, we already had a <code>sql.DB</code> object already initialized that we could use to send to <code>goose</code>. This was stored in the <code>db</code> variable.</p>
<pre><code class="language-golang">// Migrate up to the latest version
err = goose.RunMigrationsOnDb(migrateConf, migrateConf.MigrationsDir, latest, db.DB())
if err != nil {
Logger.Println(err)
return err
}
</code></pre>
<p>That&rsquo;s it! You can find our full <code>Setup()</code> function <a href="https://github.com/gophish/gophish/blob/master/models/models.go#L61">here.</a> To handle any additional migrations, all we need to do is run <code>goose create</code> again, add the SQL that makes up the migration, and push out the new file. The next time clients update gophish and restart the executable, the database migrations will be applied automatically!</p>
<p>If this kind of stuff is interesting to you, and you want to see a full example of a web app written in Go, check out gophish by clicking below.</p>
<a href="https://github.com/gophish/gophish" class="btn">Download gophish</a>
</div>
</section>
</div>
<div class="footer">
<div class="pure-menu pure-menu-horizontal pure-menu-open">
<ul>
<li>Powered by <a class="hugo" href="http://hugo.spf13.com/" target="_blank">hugo</a></li>
</ul>
</div>
</div>
<script src="https://getgophish.com/blog/js/all.min.js"></script>
</div>
</div>
</div>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-47018345-1', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>

View File

@ -63,6 +63,253 @@
<div class="posts">
<h1 class="content-subhead">01 Feb 2016, 07:00</h1>
<section class="post">
<header class="post-header">
<a href="https://getgophish.com/blog/post/database-migrations-in-go/" class="post-title">Handling Database Migrations in Go</a>
<p class="post-meta">
</p>
</header>
<div class="post-description">
<h3 id="why-you-should-version-your-database:664f01dc60472cd080b34187311f6c6f">Why You Should Version Your Database</h3>
<blockquote>
<p>&ldquo;I got my database schema correct on the first try.&rdquo;</p>
<p>-No one ever.</p>
</blockquote>
<p>Like most big projects, gophish needed a way to automatically manage changes to our database schema. As new features were being added, we found ourselves in a situation that required us to add or modify columns and tables to store the new data.</p>
<p>In a hosted environment, this is no problem since we control the database and can make schema changes as we see fit. Gophish is different, in that it is software intentionally designed to run on the client&rsquo;s machine. This means that as we rollout updates to gophish&rsquo;s backend database, we need a way to easily update (or rollback!) changes to the database structure. A versioning system is a perfect fit, which introduces the idea of migrations.</p>
<h4 id="what-is-a-migration:664f01dc60472cd080b34187311f6c6f">What is a <em>Migration</em>?</h4>
<p>A migration is nothing more than a set of SQL commands to make changes to a database. Every migration typically has two parts: how to apply the changes you want, and how to roll them back.</p>
<p>To version control our database, we can create a folder holding multiple migration files. Each file will have an identifier so we know which migration should be applied and in which order. Then, we can store which version our database is currently at in the database itself so if we ever add migrations in the future, we can tell where we left off.</p>
<p>There are tools that can automate this process for us. We settled on a well-known database migration tool called <a href="https://bitbucket.org/liamstask/goose/"><code>goose</code></a>.</p>
<h3 id="introduction-to-goose:664f01dc60472cd080b34187311f6c6f">Introduction to <code>goose</code></h3>
<p>We chose to go with <a href="https://bitbucket.org/liamstask/goose/"><code>goose</code></a> since it seemed like a mature, fully-featured solution that would be easily integrated into our code. Goose typically works through the use of its command line tool aptly named <code>goose</code>.</p>
<p>To set things up, we first need to create the following folder structure:</p>
<pre><code>| db/
| | migrations/
| `-dbconf.yml
</code></pre>
<p>Our migrations will be stored in the <code>migrations</code> folder as a series of SQL files. Before we can create migrations, we have to specify the configuration for <code>goose</code> to use. This is found in the <code>dbconf.yml</code> file. In our case, we used the following configuration:</p>
<pre><code>production:
driver: sqlite3
open: gophish.db
dialect: sqlite3
import: github.com/mattn/go-sqlite3
</code></pre>
<p>This configuration specifies a single environment, <code>production</code>, that manages a SQLite database.</p>
<p>Now that we have created our configuration file, we can start making our migrations. Unfortunately, this is where the hurdles began.</p>
<h3 id="a-little-about-gophish:664f01dc60472cd080b34187311f6c6f">A Little About Gophish</h3>
<p>Normally, migrations are something that is considered early on in the database creation process. Unfortunately, our schema was already defined and we had clients already running gophish. So, we needed to orchestrate <code>goose</code> in such a way that we could create and apply our migrations without messing up any data that was already in the client&rsquo;s databases.</p>
<p>The first step was creating the migrations. To handle this, we first created an empty migration file using the following:</p>
<pre><code>goose -env production create 0.1.2_browser_post sql
goose: created ~\go\src\github.com\gophish\gophish\db\migrations\20160130184410_0.1.2_browser_post.sql
</code></pre>
<p>This command created a new empty SQL file in our migrations folder that looks like this:</p>
<pre><code>-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied
-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back
</code></pre>
<p>For our first migration, we decided to baseline our schema to the current version. To do this, we simply exported our existing schema using the sqlite3 tool. That gave us all of our <code>CREATE TABLE</code> statements that setup our tables and default data. We then copy/pasted those statements below the <code>-- +goose Up</code> section of the migrations.</p>
<p>The one change we made was to add <code>IF NOT EXISTS</code> to all of our table creation statements. This meant that if the client already had a database setup, this migration would be applied, but no changes would be made - exactly what we want.</p>
<p>The final step to create this migration was to add the rollback statements. Since this was creating the database, <code>DROP TABLE</code> equivalent statements worked just fine. You can see our final migration file <a href="https://raw.githubusercontent.com/gophish/gophish/master/db/migrations/20160118194630_init.sql">here</a>.</p>
<p>Now for the next hurdle. Traditionally, migrations work by creating a new migration file and running <code>goose up</code>. Then, <code>goose</code> will compare your database version with the migration files it finds. If there are migrations that need to be applied, it will apply them in order until you are at the current version.</p>
<p>While the <code>goose up</code> command can work if we control the database, there&rsquo;s simply no way that we can expect our users to install <code>goose</code> and run <code>goose up</code> every time we want to make a database change. Our goal has always been to make the lives of our users easier, so this simply wouldn&rsquo;t work. This meant that we needed to handle the migrations in our code.</p>
<p>Fortunately for us, the <code>goose</code> CLI wraps a rich library that we can use. We were able to integrate this directly into our <code>Setup()</code> function to apply migrations automatically.</p>
<p>First, we created the <code>gooose.DBConf</code> struct to hold the configuration (a programmatic copy of our <code>dbconf.yml</code> file).</p>
<pre><code class="language-golang">// Setup the goose configuration
migrateConf := &amp;goose.DBConf{
MigrationsDir: config.Conf.MigrationsPath,
Env: &quot;production&quot;,
Driver: goose.DBDriver{
Name: &quot;sqlite3&quot;,
OpenStr: config.Conf.DBPath,
Import: &quot;github.com/mattn/go-sqlite3&quot;,
Dialect: &amp;goose.Sqlite3Dialect{},
},
}
</code></pre>
<p>Next, we need to figure out the latest database version supported by our migrations. This gives us the final &ldquo;goal&rdquo; migration that we want to upgrade to. We can do this via the function <a href="https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#GetMostRecentDBVersion"><code>goose.GetMostRecentDBVersion</code></a>.</p>
<pre><code class="language-golang">// Get the latest possible migration
latest, err := goose.GetMostRecentDBVersion(migrateConf.MigrationsDir)
if err != nil {
Logger.Println(err)
return err
}
</code></pre>
<p>And finally, we need to apply our migrations. <code>Goose</code> has a function called <a href="https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#RunMigrationsOnDb"><code>goose.RunMigrationsOnDb</code></a> which expects an existing <a href="https://golang.org/pkg/database/sql/#DB"><code>sql.DB</code></a> object. Since gophish uses the ORM <a href="https://github.com/jinzhu/gorm"><code>gorm</code></a>, we already had a <code>sql.DB</code> object already initialized that we could use to send to <code>goose</code>. This was stored in the <code>db</code> variable.</p>
<pre><code class="language-golang">// Migrate up to the latest version
err = goose.RunMigrationsOnDb(migrateConf, migrateConf.MigrationsDir, latest, db.DB())
if err != nil {
Logger.Println(err)
return err
}
</code></pre>
<p>That&rsquo;s it! You can find our full <code>Setup()</code> function <a href="https://github.com/gophish/gophish/blob/master/models/models.go#L61">here.</a> To handle any additional migrations, all we need to do is run <code>goose create</code> again, add the SQL that makes up the migration, and push out the new file. The next time clients update gophish and restart the executable, the database migrations will be applied automatically!</p>
<p>If this kind of stuff is interesting to you, and you want to see a full example of a web app written in Go, check out gophish by clicking below.</p>
<a href="https://github.com/gophish/gophish" class="btn">Download gophish</a>
</div>
</section>
<h1 class="content-subhead">01 Feb 2016, 06:00</h1>
<section class="post">
<header class="post-header">
<a href="https://getgophish.com/blog/post/release-0.1.1/" class="post-title">Announcing gophish v0.1.1</a>
<p class="post-meta">
</p>
</header>
<div class="post-description">
<img src="/blog/images/gophish_purple.png" alt="" class="pure-img" >
<p><em>Tl;dr - Download the release <a href="https://github.com/gophish/gophish/releases">here</a></em></p>
<h3 id="the-wait-is-over:1cea0120cd31cba0f7863bc47631176f"><strong>The wait is over!</strong></h3>
<p>The gophish team is excited to announce our first public beta version of gophish - version 0.1.1! This blog post will be a short introduction into what gophish is, as well as some of the insanely awesome features we&rsquo;ve created.</p>
<h3 id="what-is-gophish:1cea0120cd31cba0f7863bc47631176f">What is Gophish?</h3>
<p>Gophish is a phishing framework that makes the simulation of real-world phishing attacks dead-simple. The idea behind gophish is simple make industry-grade phishing training available to <em>everyone</em>.</p>
<p>&ldquo;Available&rdquo; in this case means two things </p>
<ul>
<li><strong>Affordable</strong> Gophish is currently open-source software that is completely free for anyone to use.</li>
<li><strong>Accessible</strong> Gophish is written in the Go programming language. This has the benefit that gophish releases are compiled binaries with no dependencies. In a nutshell, this makes installation as simple as “download and run”!</li>
</ul>
<h3 id="time-for-features:1cea0120cd31cba0f7863bc47631176f">Time For Features</h3>
<p>Ok, ok, enough with the intro. The idea of a phishing simulation platform isn&rsquo;t new. Let&rsquo;s take a look at some of the features that really set gophish apart and make it awesome.</p>
<h4 id="hosted-on-prem:1cea0120cd31cba0f7863bc47631176f">Hosted On-Prem</h4>
<p>There are many commercial offerings that provide phishing simulation/training. Unfortunately, these are SaaS solutions that require you to hand over your data to someone else.</p>
<p>Gophish is different in that it is meant to be hosted in-house. This keeps you data where it belongs - with you.</p>
<h4 id="download-run:1cea0120cd31cba0f7863bc47631176f">Download -&gt; Run</h4>
<p>For the few existing in-house solutions that exist, setup can be a <em>huge pain</em> (looking at you, Ruby gems). Your time is too valuable to be spent wrestling with dependencies trying to create the perfect setup that somehow magically allows the program to run.</p>
<p>Gophish was written in the Go programming language for this exact reason. To install gophish, all you have to do is download the zip file, extract the contents, and run the binary.</p>
<p>By doing this, you just started two webservers, populated a database, and setup a background worker to handle sending the mails. Now, your time can be spent making campaigns. Easy peasy.</p>
<h4 id="api-s-for-everything:1cea0120cd31cba0f7863bc47631176f">API&rsquo;s for <em>Everything</em>.</h4>
<p>Gophish was built with automation first. This means that you can create scripts and clients that automate all the hard work for you. In addition to this, we keep up-to-date <a href="/documentation/api/">API docs</a> that describe each API endpoint in detail.</p>
<h4 id="rock-solid-documentation:1cea0120cd31cba0f7863bc47631176f">Rock-Solid Documentation</h4>
<p>Speaking of API docs, we take documentation very seriously. We take documentation seriously because we take our user experience seriously. If you can&rsquo;t find what you need to use and troubleshoot gophish, we&rsquo;ve failed. Just take a look at our comprehensive <a href="/documentation/Gophish%20User%20Guide.pdf">user guide</a>, <a href="/documentation/api/">API documentation</a>, and even <a href="http://godoc.org/github.com/gophish/gophish">fully documented code</a>.</p>
<p>If you ever find something missing in our documentation, <a href="/support">we want to know!</a></p>
<h4 id="beautiful-ui:1cea0120cd31cba0f7863bc47631176f">Beautiful UI</h4>
<p>While the API is the core of gophish&rsquo;s functionality, we also provide a gorgeous admin UI. This UI is simply a wrapper on top of the underlying API. Nothing says more than screenshots:</p>
<p><figure>
<img src="/blog/images/screenshots/login.png" alt="" class="blog-image" >
<figcap>Login Screen</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/new_group.png" alt="" class="blog-image" >
<figcap>Creating a New Group</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/new_template.png" alt="" class="blog-image" >
<figcap>Creating an Email Template</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/import_site.png" alt="" class="blog-image" >
<figcap>Importing a Site</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/campaign_results.png" alt="" class="blog-image" >
<figcap>Viewing Campaign Results</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/timeline.png" alt="" class="blog-image" >
<figcap>Viewing the Timeline for a Target</figcap>
</figure>
</p>
<h3 id="take-gophish-for-a-spin:1cea0120cd31cba0f7863bc47631176f">Take Gophish for a Spin!</h3>
<p>These features only scratch the surface when it comes to what makes gophish great, and we aren&rsquo;t anywhere near done yet. To explore these features for yourself, take gophish for a spin!</p>
<p>We hope you enjoy gophish and are excited for all the new features that will be released soon! In the meantime, if you ever have any questions, comments, or issues, <a href="/support">we want to hear from you</a>!</p>
<p>-The Gophish Team</p>
<p><a href="https://github.com/gophish/gophish/releases" class="btn">Download gophish</a>
</p>
</div>
</section>
<h1 class="content-subhead">07 Jan 2016, 22:05</h1>
<section class="post">
<header class="post-header">

View File

@ -6,9 +6,240 @@
<description>Recent content in Posts on Gophish - Blog</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<lastBuildDate>Thu, 07 Jan 2016 22:05:58 -0600</lastBuildDate>
<lastBuildDate>Mon, 01 Feb 2016 07:00:00 -0600</lastBuildDate>
<atom:link href="https://getgophish.com/blog/post/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>Handling Database Migrations in Go</title>
<link>https://getgophish.com/blog/post/database-migrations-in-go/</link>
<pubDate>Mon, 01 Feb 2016 07:00:00 -0600</pubDate>
<guid>https://getgophish.com/blog/post/database-migrations-in-go/</guid>
<description>
&lt;h3 id=&#34;why-you-should-version-your-database:664f01dc60472cd080b34187311f6c6f&#34;&gt;Why You Should Version Your Database&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;I got my database schema correct on the first try.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;-No one ever.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Like most big projects, gophish needed a way to automatically manage changes to our database schema. As new features were being added, we found ourselves in a situation that required us to add or modify columns and tables to store the new data.&lt;/p&gt;
&lt;p&gt;In a hosted environment, this is no problem since we control the database and can make schema changes as we see fit. Gophish is different, in that it is software intentionally designed to run on the client&amp;rsquo;s machine. This means that as we rollout updates to gophish&amp;rsquo;s backend database, we need a way to easily update (or rollback!) changes to the database structure. A versioning system is a perfect fit, which introduces the idea of migrations.&lt;/p&gt;
&lt;h4 id=&#34;what-is-a-migration:664f01dc60472cd080b34187311f6c6f&#34;&gt;What is a &lt;em&gt;Migration&lt;/em&gt;?&lt;/h4&gt;
&lt;p&gt;A migration is nothing more than a set of SQL commands to make changes to a database. Every migration typically has two parts: how to apply the changes you want, and how to roll them back.&lt;/p&gt;
&lt;p&gt;To version control our database, we can create a folder holding multiple migration files. Each file will have an identifier so we know which migration should be applied and in which order. Then, we can store which version our database is currently at in the database itself so if we ever add migrations in the future, we can tell where we left off.&lt;/p&gt;
&lt;p&gt;There are tools that can automate this process for us. We settled on a well-known database migration tool called &lt;a href=&#34;https://bitbucket.org/liamstask/goose/&#34;&gt;&lt;code&gt;goose&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;introduction-to-goose:664f01dc60472cd080b34187311f6c6f&#34;&gt;Introduction to &lt;code&gt;goose&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;We chose to go with &lt;a href=&#34;https://bitbucket.org/liamstask/goose/&#34;&gt;&lt;code&gt;goose&lt;/code&gt;&lt;/a&gt; since it seemed like a mature, fully-featured solution that would be easily integrated into our code. Goose typically works through the use of its command line tool aptly named &lt;code&gt;goose&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To set things up, we first need to create the following folder structure:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;| db/
| | migrations/
| `-dbconf.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our migrations will be stored in the &lt;code&gt;migrations&lt;/code&gt; folder as a series of SQL files. Before we can create migrations, we have to specify the configuration for &lt;code&gt;goose&lt;/code&gt; to use. This is found in the &lt;code&gt;dbconf.yml&lt;/code&gt; file. In our case, we used the following configuration:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;production:
driver: sqlite3
open: gophish.db
dialect: sqlite3
import: github.com/mattn/go-sqlite3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This configuration specifies a single environment, &lt;code&gt;production&lt;/code&gt;, that manages a SQLite database.&lt;/p&gt;
&lt;p&gt;Now that we have created our configuration file, we can start making our migrations. Unfortunately, this is where the hurdles began.&lt;/p&gt;
&lt;h3 id=&#34;a-little-about-gophish:664f01dc60472cd080b34187311f6c6f&#34;&gt;A Little About Gophish&lt;/h3&gt;
&lt;p&gt;Normally, migrations are something that is considered early on in the database creation process. Unfortunately, our schema was already defined and we had clients already running gophish. So, we needed to orchestrate &lt;code&gt;goose&lt;/code&gt; in such a way that we could create and apply our migrations without messing up any data that was already in the client&amp;rsquo;s databases.&lt;/p&gt;
&lt;p&gt;The first step was creating the migrations. To handle this, we first created an empty migration file using the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;goose -env production create 0.1.2_browser_post sql
goose: created ~\go\src\github.com\gophish\gophish\db\migrations\20160130184410_0.1.2_browser_post.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command created a new empty SQL file in our migrations folder that looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-- +goose Up
-- SQL in section &#39;Up&#39; is executed when this migration is applied
-- +goose Down
-- SQL section &#39;Down&#39; is executed when this migration is rolled back
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For our first migration, we decided to baseline our schema to the current version. To do this, we simply exported our existing schema using the sqlite3 tool. That gave us all of our &lt;code&gt;CREATE TABLE&lt;/code&gt; statements that setup our tables and default data. We then copy/pasted those statements below the &lt;code&gt;-- +goose Up&lt;/code&gt; section of the migrations.&lt;/p&gt;
&lt;p&gt;The one change we made was to add &lt;code&gt;IF NOT EXISTS&lt;/code&gt; to all of our table creation statements. This meant that if the client already had a database setup, this migration would be applied, but no changes would be made - exactly what we want.&lt;/p&gt;
&lt;p&gt;The final step to create this migration was to add the rollback statements. Since this was creating the database, &lt;code&gt;DROP TABLE&lt;/code&gt; equivalent statements worked just fine. You can see our final migration file &lt;a href=&#34;https://raw.githubusercontent.com/gophish/gophish/master/db/migrations/20160118194630_init.sql&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now for the next hurdle. Traditionally, migrations work by creating a new migration file and running &lt;code&gt;goose up&lt;/code&gt;. Then, &lt;code&gt;goose&lt;/code&gt; will compare your database version with the migration files it finds. If there are migrations that need to be applied, it will apply them in order until you are at the current version.&lt;/p&gt;
&lt;p&gt;While the &lt;code&gt;goose up&lt;/code&gt; command can work if we control the database, there&amp;rsquo;s simply no way that we can expect our users to install &lt;code&gt;goose&lt;/code&gt; and run &lt;code&gt;goose up&lt;/code&gt; every time we want to make a database change. Our goal has always been to make the lives of our users easier, so this simply wouldn&amp;rsquo;t work. This meant that we needed to handle the migrations in our code.&lt;/p&gt;
&lt;p&gt;Fortunately for us, the &lt;code&gt;goose&lt;/code&gt; CLI wraps a rich library that we can use. We were able to integrate this directly into our &lt;code&gt;Setup()&lt;/code&gt; function to apply migrations automatically.&lt;/p&gt;
&lt;p&gt;First, we created the &lt;code&gt;gooose.DBConf&lt;/code&gt; struct to hold the configuration (a programmatic copy of our &lt;code&gt;dbconf.yml&lt;/code&gt; file).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;// Setup the goose configuration
migrateConf := &amp;amp;goose.DBConf{
MigrationsDir: config.Conf.MigrationsPath,
Env: &amp;quot;production&amp;quot;,
Driver: goose.DBDriver{
Name: &amp;quot;sqlite3&amp;quot;,
OpenStr: config.Conf.DBPath,
Import: &amp;quot;github.com/mattn/go-sqlite3&amp;quot;,
Dialect: &amp;amp;goose.Sqlite3Dialect{},
},
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we need to figure out the latest database version supported by our migrations. This gives us the final &amp;ldquo;goal&amp;rdquo; migration that we want to upgrade to. We can do this via the function &lt;a href=&#34;https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#GetMostRecentDBVersion&#34;&gt;&lt;code&gt;goose.GetMostRecentDBVersion&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;// Get the latest possible migration
latest, err := goose.GetMostRecentDBVersion(migrateConf.MigrationsDir)
if err != nil {
Logger.Println(err)
return err
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally, we need to apply our migrations. &lt;code&gt;Goose&lt;/code&gt; has a function called &lt;a href=&#34;https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#RunMigrationsOnDb&#34;&gt;&lt;code&gt;goose.RunMigrationsOnDb&lt;/code&gt;&lt;/a&gt; which expects an existing &lt;a href=&#34;https://golang.org/pkg/database/sql/#DB&#34;&gt;&lt;code&gt;sql.DB&lt;/code&gt;&lt;/a&gt; object. Since gophish uses the ORM &lt;a href=&#34;https://github.com/jinzhu/gorm&#34;&gt;&lt;code&gt;gorm&lt;/code&gt;&lt;/a&gt;, we already had a &lt;code&gt;sql.DB&lt;/code&gt; object already initialized that we could use to send to &lt;code&gt;goose&lt;/code&gt;. This was stored in the &lt;code&gt;db&lt;/code&gt; variable.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;// Migrate up to the latest version
err = goose.RunMigrationsOnDb(migrateConf, migrateConf.MigrationsDir, latest, db.DB())
if err != nil {
Logger.Println(err)
return err
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;rsquo;s it! You can find our full &lt;code&gt;Setup()&lt;/code&gt; function &lt;a href=&#34;https://github.com/gophish/gophish/blob/master/models/models.go#L61&#34;&gt;here.&lt;/a&gt; To handle any additional migrations, all we need to do is run &lt;code&gt;goose create&lt;/code&gt; again, add the SQL that makes up the migration, and push out the new file. The next time clients update gophish and restart the executable, the database migrations will be applied automatically!&lt;/p&gt;
&lt;p&gt;If this kind of stuff is interesting to you, and you want to see a full example of a web app written in Go, check out gophish by clicking below.&lt;/p&gt;
&lt;a href=&#34;https://github.com/gophish/gophish&#34; class=&#34;btn&#34;&gt;Download gophish&lt;/a&gt;
</description>
</item>
<item>
<title>Announcing gophish v0.1.1</title>
<link>https://getgophish.com/blog/post/release-0.1.1/</link>
<pubDate>Mon, 01 Feb 2016 06:00:00 -0600</pubDate>
<guid>https://getgophish.com/blog/post/release-0.1.1/</guid>
<description>
&lt;img src=&#34;https://getgophish.com/blog/blog/images/gophish_purple.png&#34; alt=&#34;&#34; class=&#34;pure-img&#34; &gt;
&lt;p&gt;&lt;em&gt;Tl;dr - Download the release &lt;a href=&#34;https://github.com/gophish/gophish/releases&#34;&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;the-wait-is-over:1cea0120cd31cba0f7863bc47631176f&#34;&gt;&lt;strong&gt;The wait is over!&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The gophish team is excited to announce our first public beta version of gophish - version 0.1.1! This blog post will be a short introduction into what gophish is, as well as some of the insanely awesome features we&amp;rsquo;ve created.&lt;/p&gt;
&lt;h3 id=&#34;what-is-gophish:1cea0120cd31cba0f7863bc47631176f&#34;&gt;What is Gophish?&lt;/h3&gt;
&lt;p&gt;Gophish is a phishing framework that makes the simulation of real-world phishing attacks dead-simple. The idea behind gophish is simple make industry-grade phishing training available to &lt;em&gt;everyone&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Available&amp;rdquo; in this case means two things &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Affordable&lt;/strong&gt; Gophish is currently open-source software that is completely free for anyone to use.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accessible&lt;/strong&gt; Gophish is written in the Go programming language. This has the benefit that gophish releases are compiled binaries with no dependencies. In a nutshell, this makes installation as simple as “download and run”!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;time-for-features:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Time For Features&lt;/h3&gt;
&lt;p&gt;Ok, ok, enough with the intro. The idea of a phishing simulation platform isn&amp;rsquo;t new. Let&amp;rsquo;s take a look at some of the features that really set gophish apart and make it awesome.&lt;/p&gt;
&lt;h4 id=&#34;hosted-on-prem:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Hosted On-Prem&lt;/h4&gt;
&lt;p&gt;There are many commercial offerings that provide phishing simulation/training. Unfortunately, these are SaaS solutions that require you to hand over your data to someone else.&lt;/p&gt;
&lt;p&gt;Gophish is different in that it is meant to be hosted in-house. This keeps you data where it belongs - with you.&lt;/p&gt;
&lt;h4 id=&#34;download-run:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Download -&amp;gt; Run&lt;/h4&gt;
&lt;p&gt;For the few existing in-house solutions that exist, setup can be a &lt;em&gt;huge pain&lt;/em&gt; (looking at you, Ruby gems). Your time is too valuable to be spent wrestling with dependencies trying to create the perfect setup that somehow magically allows the program to run.&lt;/p&gt;
&lt;p&gt;Gophish was written in the Go programming language for this exact reason. To install gophish, all you have to do is download the zip file, extract the contents, and run the binary.&lt;/p&gt;
&lt;p&gt;By doing this, you just started two webservers, populated a database, and setup a background worker to handle sending the mails. Now, your time can be spent making campaigns. Easy peasy.&lt;/p&gt;
&lt;h4 id=&#34;api-s-for-everything:1cea0120cd31cba0f7863bc47631176f&#34;&gt;API&amp;rsquo;s for &lt;em&gt;Everything&lt;/em&gt;.&lt;/h4&gt;
&lt;p&gt;Gophish was built with automation first. This means that you can create scripts and clients that automate all the hard work for you. In addition to this, we keep up-to-date &lt;a href=&#34;https://getgophish.com/blog/documentation/api/&#34;&gt;API docs&lt;/a&gt; that describe each API endpoint in detail.&lt;/p&gt;
&lt;h4 id=&#34;rock-solid-documentation:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Rock-Solid Documentation&lt;/h4&gt;
&lt;p&gt;Speaking of API docs, we take documentation very seriously. We take documentation seriously because we take our user experience seriously. If you can&amp;rsquo;t find what you need to use and troubleshoot gophish, we&amp;rsquo;ve failed. Just take a look at our comprehensive &lt;a href=&#34;https://getgophish.com/blog/documentation/Gophish%20User%20Guide.pdf&#34;&gt;user guide&lt;/a&gt;, &lt;a href=&#34;https://getgophish.com/blog/documentation/api/&#34;&gt;API documentation&lt;/a&gt;, and even &lt;a href=&#34;http://godoc.org/github.com/gophish/gophish&#34;&gt;fully documented code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you ever find something missing in our documentation, &lt;a href=&#34;https://getgophish.com/blog/support&#34;&gt;we want to know!&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&#34;beautiful-ui:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Beautiful UI&lt;/h4&gt;
&lt;p&gt;While the API is the core of gophish&amp;rsquo;s functionality, we also provide a gorgeous admin UI. This UI is simply a wrapper on top of the underlying API. Nothing says more than screenshots:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/login.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Login Screen&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/new_group.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Creating a New Group&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/new_template.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Creating an Email Template&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/import_site.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Importing a Site&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/campaign_results.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Viewing Campaign Results&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/timeline.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Viewing the Timeline for a Target&lt;/figcap&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id=&#34;take-gophish-for-a-spin:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Take Gophish for a Spin!&lt;/h3&gt;
&lt;p&gt;These features only scratch the surface when it comes to what makes gophish great, and we aren&amp;rsquo;t anywhere near done yet. To explore these features for yourself, take gophish for a spin!&lt;/p&gt;
&lt;p&gt;We hope you enjoy gophish and are excited for all the new features that will be released soon! In the meantime, if you ever have any questions, comments, or issues, &lt;a href=&#34;https://getgophish.com/blog/support&#34;&gt;we want to hear from you&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;-The Gophish Team&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/gophish/gophish/releases&#34; class=&#34;btn&#34;&gt;Download gophish&lt;/a&gt;
&lt;/p&gt;
</description>
</item>
<item>
<title>Introducing gophish</title>
<link>https://getgophish.com/blog/post/hello-world/</link>

View File

@ -0,0 +1,202 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Announcing gophish v0.1.1 &middot; Gophish - Blog</title>
<meta name="description" content="">
<meta name="generator" content="Hugo 0.15" />
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Announcing gophish v0.1.1 &middot; Gophish - Blog">
<meta name="twitter:description" content="">
<meta property="og:type" content="article">
<meta property="og:title" content="Announcing gophish v0.1.1 &middot; Gophish - Blog">
<meta property="og:description" content="">
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700|Oxygen:400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/pure-min.css">
<!--[if lte IE 8]>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/grids-responsive-old-ie-min.css">
<![endif]-->
<!--[if gt IE 8]><!-->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/grids-responsive-min.css">
<!--<![endif]-->
<link rel="stylesheet" href="https://getgophish.com/blog/css/all.min.css">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="alternate" type="application/rss+xml" title="Gophish - Blog" href="https://getgophish.com/blog/index.xml" />
</head>
<body>
<div id="layout" class="pure-g">
<div class="sidebar pure-u-1 pure-u-md-1-4">
<div class="header">
<hgroup>
<h1 class="brand-title"><a href="https://getgophish.com/blog">Gophish - Blog</a></h1>
<h2 class="brand-tagline"></h2>
</hgroup>
<nav class="nav">
<ul class="nav-list">
<li class="nav-item">
<a class="pure-button" href="http://getgophish.com"><i class="fa fa-home"></i> home</a>
</li>
<li class="nav-item">
<a class="pure-button" href="https://getgophish.com/blog/index.xml"><i class="fa fa-rss"></i> rss</a>
</li>
</ul>
</nav>
</div>
</div>
<div class="content pure-u-1 pure-u-md-3-4">
<div>
<div class="posts">
<h1 class="content-subhead">01 Feb 2016, 06:00</h1>
<section class="post">
<header class="post-header">
<a href="https://getgophish.com/blog/post/release-0.1.1/" class="post-title">Announcing gophish v0.1.1</a>
<p class="post-meta">
</p>
</header>
<div class="post-description">
<img src="/blog/images/gophish_purple.png" alt="" class="pure-img" >
<p><em>Tl;dr - Download the release <a href="https://github.com/gophish/gophish/releases">here</a></em></p>
<h3 id="the-wait-is-over:1cea0120cd31cba0f7863bc47631176f"><strong>The wait is over!</strong></h3>
<p>The gophish team is excited to announce our first public beta version of gophish - version 0.1.1! This blog post will be a short introduction into what gophish is, as well as some of the insanely awesome features we&rsquo;ve created.</p>
<h3 id="what-is-gophish:1cea0120cd31cba0f7863bc47631176f">What is Gophish?</h3>
<p>Gophish is a phishing framework that makes the simulation of real-world phishing attacks dead-simple. The idea behind gophish is simple make industry-grade phishing training available to <em>everyone</em>.</p>
<p>&ldquo;Available&rdquo; in this case means two things </p>
<ul>
<li><strong>Affordable</strong> Gophish is currently open-source software that is completely free for anyone to use.</li>
<li><strong>Accessible</strong> Gophish is written in the Go programming language. This has the benefit that gophish releases are compiled binaries with no dependencies. In a nutshell, this makes installation as simple as “download and run”!</li>
</ul>
<h3 id="time-for-features:1cea0120cd31cba0f7863bc47631176f">Time For Features</h3>
<p>Ok, ok, enough with the intro. The idea of a phishing simulation platform isn&rsquo;t new. Let&rsquo;s take a look at some of the features that really set gophish apart and make it awesome.</p>
<h4 id="hosted-on-prem:1cea0120cd31cba0f7863bc47631176f">Hosted On-Prem</h4>
<p>There are many commercial offerings that provide phishing simulation/training. Unfortunately, these are SaaS solutions that require you to hand over your data to someone else.</p>
<p>Gophish is different in that it is meant to be hosted in-house. This keeps you data where it belongs - with you.</p>
<h4 id="download-run:1cea0120cd31cba0f7863bc47631176f">Download -&gt; Run</h4>
<p>For the few existing in-house solutions that exist, setup can be a <em>huge pain</em> (looking at you, Ruby gems). Your time is too valuable to be spent wrestling with dependencies trying to create the perfect setup that somehow magically allows the program to run.</p>
<p>Gophish was written in the Go programming language for this exact reason. To install gophish, all you have to do is download the zip file, extract the contents, and run the binary.</p>
<p>By doing this, you just started two webservers, populated a database, and setup a background worker to handle sending the mails. Now, your time can be spent making campaigns. Easy peasy.</p>
<h4 id="api-s-for-everything:1cea0120cd31cba0f7863bc47631176f">API&rsquo;s for <em>Everything</em>.</h4>
<p>Gophish was built with automation first. This means that you can create scripts and clients that automate all the hard work for you. In addition to this, we keep up-to-date <a href="/documentation/api/">API docs</a> that describe each API endpoint in detail.</p>
<h4 id="rock-solid-documentation:1cea0120cd31cba0f7863bc47631176f">Rock-Solid Documentation</h4>
<p>Speaking of API docs, we take documentation very seriously. We take documentation seriously because we take our user experience seriously. If you can&rsquo;t find what you need to use and troubleshoot gophish, we&rsquo;ve failed. Just take a look at our comprehensive <a href="/documentation/Gophish%20User%20Guide.pdf">user guide</a>, <a href="/documentation/api/">API documentation</a>, and even <a href="http://godoc.org/github.com/gophish/gophish">fully documented code</a>.</p>
<p>If you ever find something missing in our documentation, <a href="/support">we want to know!</a></p>
<h4 id="beautiful-ui:1cea0120cd31cba0f7863bc47631176f">Beautiful UI</h4>
<p>While the API is the core of gophish&rsquo;s functionality, we also provide a gorgeous admin UI. This UI is simply a wrapper on top of the underlying API. Nothing says more than screenshots:</p>
<p><figure>
<img src="/blog/images/screenshots/login.png" alt="" class="blog-image" >
<figcap>Login Screen</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/new_group.png" alt="" class="blog-image" >
<figcap>Creating a New Group</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/new_template.png" alt="" class="blog-image" >
<figcap>Creating an Email Template</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/import_site.png" alt="" class="blog-image" >
<figcap>Importing a Site</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/campaign_results.png" alt="" class="blog-image" >
<figcap>Viewing Campaign Results</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/timeline.png" alt="" class="blog-image" >
<figcap>Viewing the Timeline for a Target</figcap>
</figure>
</p>
<h3 id="take-gophish-for-a-spin:1cea0120cd31cba0f7863bc47631176f">Take Gophish for a Spin!</h3>
<p>These features only scratch the surface when it comes to what makes gophish great, and we aren&rsquo;t anywhere near done yet. To explore these features for yourself, take gophish for a spin!</p>
<p>We hope you enjoy gophish and are excited for all the new features that will be released soon! In the meantime, if you ever have any questions, comments, or issues, <a href="/support">we want to hear from you</a>!</p>
<p>-The Gophish Team</p>
<p><a href="https://github.com/gophish/gophish/releases" class="btn">Download gophish</a>
</p>
</div>
</section>
</div>
<div class="footer">
<div class="pure-menu pure-menu-horizontal pure-menu-open">
<ul>
<li>Powered by <a class="hugo" href="http://hugo.spf13.com/" target="_blank">hugo</a></li>
</ul>
</div>
</div>
<script src="https://getgophish.com/blog/js/all.min.js"></script>
</div>
</div>
</div>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-47018345-1', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
blog/screenshots/login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -3,10 +3,20 @@
<url>
<loc>https://getgophish.com/blog/</loc>
<lastmod>2016-01-07T22:05:58-06:00</lastmod>
<lastmod>2016-02-01T07:00:00-06:00</lastmod>
<priority>0</priority>
</url>
<url>
<loc>https://getgophish.com/blog/post/database-migrations-in-go/</loc>
<lastmod>2016-02-01T07:00:00-06:00</lastmod>
</url>
<url>
<loc>https://getgophish.com/blog/post/release-0.1.1/</loc>
<lastmod>2016-02-01T06:00:00-06:00</lastmod>
</url>
<url>
<loc>https://getgophish.com/blog/post/hello-world/</loc>
<lastmod>2016-01-07T22:05:58-06:00</lastmod>

View File

@ -0,0 +1,229 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Engineering &middot; Gophish - Blog</title>
<meta name="description" content="">
<meta name="generator" content="Hugo 0.15" />
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Engineering &middot; Gophish - Blog">
<meta name="twitter:description" content="">
<meta property="og:type" content="article">
<meta property="og:title" content="Engineering &middot; Gophish - Blog">
<meta property="og:description" content="">
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700|Oxygen:400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/pure-min.css">
<!--[if lte IE 8]>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/grids-responsive-old-ie-min.css">
<![endif]-->
<!--[if gt IE 8]><!-->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/grids-responsive-min.css">
<!--<![endif]-->
<link rel="stylesheet" href="https://getgophish.com/blog/css/all.min.css">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="alternate" type="application/rss+xml" title="Gophish - Blog" href="https://getgophish.com/blog/index.xml" />
</head>
<body>
<div id="layout" class="pure-g">
<div class="sidebar pure-u-1 pure-u-md-1-4">
<div class="header">
<hgroup>
<h1 class="brand-title"><a href="https://getgophish.com/blog">Gophish - Blog</a></h1>
<h2 class="brand-tagline"></h2>
</hgroup>
<nav class="nav">
<ul class="nav-list">
<li class="nav-item">
<a class="pure-button" href="http://getgophish.com"><i class="fa fa-home"></i> home</a>
</li>
<li class="nav-item">
<a class="pure-button" href="https://getgophish.com/blog/index.xml"><i class="fa fa-rss"></i> rss</a>
</li>
</ul>
</nav>
</div>
</div>
<div class="content pure-u-1 pure-u-md-3-4">
<div>
<div class="posts">
<h1 class="content-subhead">01 Feb 2016, 07:00</h1>
<section class="post">
<header class="post-header">
<a href="https://getgophish.com/blog/post/database-migrations-in-go/" class="post-title">Handling Database Migrations in Go</a>
<p class="post-meta">
</p>
</header>
<div class="post-description">
<h3 id="why-you-should-version-your-database:664f01dc60472cd080b34187311f6c6f">Why You Should Version Your Database</h3>
<blockquote>
<p>&ldquo;I got my database schema correct on the first try.&rdquo;</p>
<p>-No one ever.</p>
</blockquote>
<p>Like most big projects, gophish needed a way to automatically manage changes to our database schema. As new features were being added, we found ourselves in a situation that required us to add or modify columns and tables to store the new data.</p>
<p>In a hosted environment, this is no problem since we control the database and can make schema changes as we see fit. Gophish is different, in that it is software intentionally designed to run on the client&rsquo;s machine. This means that as we rollout updates to gophish&rsquo;s backend database, we need a way to easily update (or rollback!) changes to the database structure. A versioning system is a perfect fit, which introduces the idea of migrations.</p>
<h4 id="what-is-a-migration:664f01dc60472cd080b34187311f6c6f">What is a <em>Migration</em>?</h4>
<p>A migration is nothing more than a set of SQL commands to make changes to a database. Every migration typically has two parts: how to apply the changes you want, and how to roll them back.</p>
<p>To version control our database, we can create a folder holding multiple migration files. Each file will have an identifier so we know which migration should be applied and in which order. Then, we can store which version our database is currently at in the database itself so if we ever add migrations in the future, we can tell where we left off.</p>
<p>There are tools that can automate this process for us. We settled on a well-known database migration tool called <a href="https://bitbucket.org/liamstask/goose/"><code>goose</code></a>.</p>
<h3 id="introduction-to-goose:664f01dc60472cd080b34187311f6c6f">Introduction to <code>goose</code></h3>
<p>We chose to go with <a href="https://bitbucket.org/liamstask/goose/"><code>goose</code></a> since it seemed like a mature, fully-featured solution that would be easily integrated into our code. Goose typically works through the use of its command line tool aptly named <code>goose</code>.</p>
<p>To set things up, we first need to create the following folder structure:</p>
<pre><code>| db/
| | migrations/
| `-dbconf.yml
</code></pre>
<p>Our migrations will be stored in the <code>migrations</code> folder as a series of SQL files. Before we can create migrations, we have to specify the configuration for <code>goose</code> to use. This is found in the <code>dbconf.yml</code> file. In our case, we used the following configuration:</p>
<pre><code>production:
driver: sqlite3
open: gophish.db
dialect: sqlite3
import: github.com/mattn/go-sqlite3
</code></pre>
<p>This configuration specifies a single environment, <code>production</code>, that manages a SQLite database.</p>
<p>Now that we have created our configuration file, we can start making our migrations. Unfortunately, this is where the hurdles began.</p>
<h3 id="a-little-about-gophish:664f01dc60472cd080b34187311f6c6f">A Little About Gophish</h3>
<p>Normally, migrations are something that is considered early on in the database creation process. Unfortunately, our schema was already defined and we had clients already running gophish. So, we needed to orchestrate <code>goose</code> in such a way that we could create and apply our migrations without messing up any data that was already in the client&rsquo;s databases.</p>
<p>The first step was creating the migrations. To handle this, we first created an empty migration file using the following:</p>
<pre><code>goose -env production create 0.1.2_browser_post sql
goose: created ~\go\src\github.com\gophish\gophish\db\migrations\20160130184410_0.1.2_browser_post.sql
</code></pre>
<p>This command created a new empty SQL file in our migrations folder that looks like this:</p>
<pre><code>-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied
-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back
</code></pre>
<p>For our first migration, we decided to baseline our schema to the current version. To do this, we simply exported our existing schema using the sqlite3 tool. That gave us all of our <code>CREATE TABLE</code> statements that setup our tables and default data. We then copy/pasted those statements below the <code>-- +goose Up</code> section of the migrations.</p>
<p>The one change we made was to add <code>IF NOT EXISTS</code> to all of our table creation statements. This meant that if the client already had a database setup, this migration would be applied, but no changes would be made - exactly what we want.</p>
<p>The final step to create this migration was to add the rollback statements. Since this was creating the database, <code>DROP TABLE</code> equivalent statements worked just fine. You can see our final migration file <a href="https://raw.githubusercontent.com/gophish/gophish/master/db/migrations/20160118194630_init.sql">here</a>.</p>
<p>Now for the next hurdle. Traditionally, migrations work by creating a new migration file and running <code>goose up</code>. Then, <code>goose</code> will compare your database version with the migration files it finds. If there are migrations that need to be applied, it will apply them in order until you are at the current version.</p>
<p>While the <code>goose up</code> command can work if we control the database, there&rsquo;s simply no way that we can expect our users to install <code>goose</code> and run <code>goose up</code> every time we want to make a database change. Our goal has always been to make the lives of our users easier, so this simply wouldn&rsquo;t work. This meant that we needed to handle the migrations in our code.</p>
<p>Fortunately for us, the <code>goose</code> CLI wraps a rich library that we can use. We were able to integrate this directly into our <code>Setup()</code> function to apply migrations automatically.</p>
<p>First, we created the <code>gooose.DBConf</code> struct to hold the configuration (a programmatic copy of our <code>dbconf.yml</code> file).</p>
<pre><code class="language-golang">// Setup the goose configuration
migrateConf := &amp;goose.DBConf{
MigrationsDir: config.Conf.MigrationsPath,
Env: &quot;production&quot;,
Driver: goose.DBDriver{
Name: &quot;sqlite3&quot;,
OpenStr: config.Conf.DBPath,
Import: &quot;github.com/mattn/go-sqlite3&quot;,
Dialect: &amp;goose.Sqlite3Dialect{},
},
}
</code></pre>
<p>Next, we need to figure out the latest database version supported by our migrations. This gives us the final &ldquo;goal&rdquo; migration that we want to upgrade to. We can do this via the function <a href="https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#GetMostRecentDBVersion"><code>goose.GetMostRecentDBVersion</code></a>.</p>
<pre><code class="language-golang">// Get the latest possible migration
latest, err := goose.GetMostRecentDBVersion(migrateConf.MigrationsDir)
if err != nil {
Logger.Println(err)
return err
}
</code></pre>
<p>And finally, we need to apply our migrations. <code>Goose</code> has a function called <a href="https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#RunMigrationsOnDb"><code>goose.RunMigrationsOnDb</code></a> which expects an existing <a href="https://golang.org/pkg/database/sql/#DB"><code>sql.DB</code></a> object. Since gophish uses the ORM <a href="https://github.com/jinzhu/gorm"><code>gorm</code></a>, we already had a <code>sql.DB</code> object already initialized that we could use to send to <code>goose</code>. This was stored in the <code>db</code> variable.</p>
<pre><code class="language-golang">// Migrate up to the latest version
err = goose.RunMigrationsOnDb(migrateConf, migrateConf.MigrationsDir, latest, db.DB())
if err != nil {
Logger.Println(err)
return err
}
</code></pre>
<p>That&rsquo;s it! You can find our full <code>Setup()</code> function <a href="https://github.com/gophish/gophish/blob/master/models/models.go#L61">here.</a> To handle any additional migrations, all we need to do is run <code>goose create</code> again, add the SQL that makes up the migration, and push out the new file. The next time clients update gophish and restart the executable, the database migrations will be applied automatically!</p>
<p>If this kind of stuff is interesting to you, and you want to see a full example of a web app written in Go, check out gophish by clicking below.</p>
<a href="https://github.com/gophish/gophish" class="btn">Download gophish</a>
</div>
</section>
</div>
<div class="footer">
<div class="pure-menu pure-menu-horizontal pure-menu-open">
<ul>
<li>Powered by <a class="hugo" href="http://hugo.spf13.com/" target="_blank">hugo</a></li>
</ul>
</div>
</div>
<script src="https://getgophish.com/blog/js/all.min.js"></script>
</div>
</div>
</div>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-47018345-1', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>

View File

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Engineering on Gophish - Blog</title>
<link>https://getgophish.com/blog/tags/engineering/</link>
<description>Recent content in Engineering on Gophish - Blog</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<lastBuildDate>Mon, 01 Feb 2016 07:00:00 -0600</lastBuildDate>
<atom:link href="https://getgophish.com/blog/tags/engineering/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>Handling Database Migrations in Go</title>
<link>https://getgophish.com/blog/post/database-migrations-in-go/</link>
<pubDate>Mon, 01 Feb 2016 07:00:00 -0600</pubDate>
<guid>https://getgophish.com/blog/post/database-migrations-in-go/</guid>
<description>
&lt;h3 id=&#34;why-you-should-version-your-database:664f01dc60472cd080b34187311f6c6f&#34;&gt;Why You Should Version Your Database&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;I got my database schema correct on the first try.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;-No one ever.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Like most big projects, gophish needed a way to automatically manage changes to our database schema. As new features were being added, we found ourselves in a situation that required us to add or modify columns and tables to store the new data.&lt;/p&gt;
&lt;p&gt;In a hosted environment, this is no problem since we control the database and can make schema changes as we see fit. Gophish is different, in that it is software intentionally designed to run on the client&amp;rsquo;s machine. This means that as we rollout updates to gophish&amp;rsquo;s backend database, we need a way to easily update (or rollback!) changes to the database structure. A versioning system is a perfect fit, which introduces the idea of migrations.&lt;/p&gt;
&lt;h4 id=&#34;what-is-a-migration:664f01dc60472cd080b34187311f6c6f&#34;&gt;What is a &lt;em&gt;Migration&lt;/em&gt;?&lt;/h4&gt;
&lt;p&gt;A migration is nothing more than a set of SQL commands to make changes to a database. Every migration typically has two parts: how to apply the changes you want, and how to roll them back.&lt;/p&gt;
&lt;p&gt;To version control our database, we can create a folder holding multiple migration files. Each file will have an identifier so we know which migration should be applied and in which order. Then, we can store which version our database is currently at in the database itself so if we ever add migrations in the future, we can tell where we left off.&lt;/p&gt;
&lt;p&gt;There are tools that can automate this process for us. We settled on a well-known database migration tool called &lt;a href=&#34;https://bitbucket.org/liamstask/goose/&#34;&gt;&lt;code&gt;goose&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;introduction-to-goose:664f01dc60472cd080b34187311f6c6f&#34;&gt;Introduction to &lt;code&gt;goose&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;We chose to go with &lt;a href=&#34;https://bitbucket.org/liamstask/goose/&#34;&gt;&lt;code&gt;goose&lt;/code&gt;&lt;/a&gt; since it seemed like a mature, fully-featured solution that would be easily integrated into our code. Goose typically works through the use of its command line tool aptly named &lt;code&gt;goose&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To set things up, we first need to create the following folder structure:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;| db/
| | migrations/
| `-dbconf.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our migrations will be stored in the &lt;code&gt;migrations&lt;/code&gt; folder as a series of SQL files. Before we can create migrations, we have to specify the configuration for &lt;code&gt;goose&lt;/code&gt; to use. This is found in the &lt;code&gt;dbconf.yml&lt;/code&gt; file. In our case, we used the following configuration:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;production:
driver: sqlite3
open: gophish.db
dialect: sqlite3
import: github.com/mattn/go-sqlite3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This configuration specifies a single environment, &lt;code&gt;production&lt;/code&gt;, that manages a SQLite database.&lt;/p&gt;
&lt;p&gt;Now that we have created our configuration file, we can start making our migrations. Unfortunately, this is where the hurdles began.&lt;/p&gt;
&lt;h3 id=&#34;a-little-about-gophish:664f01dc60472cd080b34187311f6c6f&#34;&gt;A Little About Gophish&lt;/h3&gt;
&lt;p&gt;Normally, migrations are something that is considered early on in the database creation process. Unfortunately, our schema was already defined and we had clients already running gophish. So, we needed to orchestrate &lt;code&gt;goose&lt;/code&gt; in such a way that we could create and apply our migrations without messing up any data that was already in the client&amp;rsquo;s databases.&lt;/p&gt;
&lt;p&gt;The first step was creating the migrations. To handle this, we first created an empty migration file using the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;goose -env production create 0.1.2_browser_post sql
goose: created ~\go\src\github.com\gophish\gophish\db\migrations\20160130184410_0.1.2_browser_post.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command created a new empty SQL file in our migrations folder that looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-- +goose Up
-- SQL in section &#39;Up&#39; is executed when this migration is applied
-- +goose Down
-- SQL section &#39;Down&#39; is executed when this migration is rolled back
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For our first migration, we decided to baseline our schema to the current version. To do this, we simply exported our existing schema using the sqlite3 tool. That gave us all of our &lt;code&gt;CREATE TABLE&lt;/code&gt; statements that setup our tables and default data. We then copy/pasted those statements below the &lt;code&gt;-- +goose Up&lt;/code&gt; section of the migrations.&lt;/p&gt;
&lt;p&gt;The one change we made was to add &lt;code&gt;IF NOT EXISTS&lt;/code&gt; to all of our table creation statements. This meant that if the client already had a database setup, this migration would be applied, but no changes would be made - exactly what we want.&lt;/p&gt;
&lt;p&gt;The final step to create this migration was to add the rollback statements. Since this was creating the database, &lt;code&gt;DROP TABLE&lt;/code&gt; equivalent statements worked just fine. You can see our final migration file &lt;a href=&#34;https://raw.githubusercontent.com/gophish/gophish/master/db/migrations/20160118194630_init.sql&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now for the next hurdle. Traditionally, migrations work by creating a new migration file and running &lt;code&gt;goose up&lt;/code&gt;. Then, &lt;code&gt;goose&lt;/code&gt; will compare your database version with the migration files it finds. If there are migrations that need to be applied, it will apply them in order until you are at the current version.&lt;/p&gt;
&lt;p&gt;While the &lt;code&gt;goose up&lt;/code&gt; command can work if we control the database, there&amp;rsquo;s simply no way that we can expect our users to install &lt;code&gt;goose&lt;/code&gt; and run &lt;code&gt;goose up&lt;/code&gt; every time we want to make a database change. Our goal has always been to make the lives of our users easier, so this simply wouldn&amp;rsquo;t work. This meant that we needed to handle the migrations in our code.&lt;/p&gt;
&lt;p&gt;Fortunately for us, the &lt;code&gt;goose&lt;/code&gt; CLI wraps a rich library that we can use. We were able to integrate this directly into our &lt;code&gt;Setup()&lt;/code&gt; function to apply migrations automatically.&lt;/p&gt;
&lt;p&gt;First, we created the &lt;code&gt;gooose.DBConf&lt;/code&gt; struct to hold the configuration (a programmatic copy of our &lt;code&gt;dbconf.yml&lt;/code&gt; file).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;// Setup the goose configuration
migrateConf := &amp;amp;goose.DBConf{
MigrationsDir: config.Conf.MigrationsPath,
Env: &amp;quot;production&amp;quot;,
Driver: goose.DBDriver{
Name: &amp;quot;sqlite3&amp;quot;,
OpenStr: config.Conf.DBPath,
Import: &amp;quot;github.com/mattn/go-sqlite3&amp;quot;,
Dialect: &amp;amp;goose.Sqlite3Dialect{},
},
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we need to figure out the latest database version supported by our migrations. This gives us the final &amp;ldquo;goal&amp;rdquo; migration that we want to upgrade to. We can do this via the function &lt;a href=&#34;https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#GetMostRecentDBVersion&#34;&gt;&lt;code&gt;goose.GetMostRecentDBVersion&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;// Get the latest possible migration
latest, err := goose.GetMostRecentDBVersion(migrateConf.MigrationsDir)
if err != nil {
Logger.Println(err)
return err
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally, we need to apply our migrations. &lt;code&gt;Goose&lt;/code&gt; has a function called &lt;a href=&#34;https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#RunMigrationsOnDb&#34;&gt;&lt;code&gt;goose.RunMigrationsOnDb&lt;/code&gt;&lt;/a&gt; which expects an existing &lt;a href=&#34;https://golang.org/pkg/database/sql/#DB&#34;&gt;&lt;code&gt;sql.DB&lt;/code&gt;&lt;/a&gt; object. Since gophish uses the ORM &lt;a href=&#34;https://github.com/jinzhu/gorm&#34;&gt;&lt;code&gt;gorm&lt;/code&gt;&lt;/a&gt;, we already had a &lt;code&gt;sql.DB&lt;/code&gt; object already initialized that we could use to send to &lt;code&gt;goose&lt;/code&gt;. This was stored in the &lt;code&gt;db&lt;/code&gt; variable.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;// Migrate up to the latest version
err = goose.RunMigrationsOnDb(migrateConf, migrateConf.MigrationsDir, latest, db.DB())
if err != nil {
Logger.Println(err)
return err
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;rsquo;s it! You can find our full &lt;code&gt;Setup()&lt;/code&gt; function &lt;a href=&#34;https://github.com/gophish/gophish/blob/master/models/models.go#L61&#34;&gt;here.&lt;/a&gt; To handle any additional migrations, all we need to do is run &lt;code&gt;goose create&lt;/code&gt; again, add the SQL that makes up the migration, and push out the new file. The next time clients update gophish and restart the executable, the database migrations will be applied automatically!&lt;/p&gt;
&lt;p&gt;If this kind of stuff is interesting to you, and you want to see a full example of a web app written in Go, check out gophish by clicking below.&lt;/p&gt;
&lt;a href=&#34;https://github.com/gophish/gophish&#34; class=&#34;btn&#34;&gt;Download gophish&lt;/a&gt;
</description>
</item>
</channel>
</rss>

View File

@ -0,0 +1 @@
<!DOCTYPE html><html><head><link rel="canonical" href="https://getgophish.com/blog/tags/engineering/"/><meta http-equiv="content-type" content="text/html; charset=utf-8" /><meta http-equiv="refresh" content="0;url=https://getgophish.com/blog/tags/engineering/" /></head></html>

229
blog/tags/go/index.html Normal file
View File

@ -0,0 +1,229 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Go &middot; Gophish - Blog</title>
<meta name="description" content="">
<meta name="generator" content="Hugo 0.15" />
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Go &middot; Gophish - Blog">
<meta name="twitter:description" content="">
<meta property="og:type" content="article">
<meta property="og:title" content="Go &middot; Gophish - Blog">
<meta property="og:description" content="">
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700|Oxygen:400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/pure-min.css">
<!--[if lte IE 8]>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/grids-responsive-old-ie-min.css">
<![endif]-->
<!--[if gt IE 8]><!-->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/grids-responsive-min.css">
<!--<![endif]-->
<link rel="stylesheet" href="https://getgophish.com/blog/css/all.min.css">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="alternate" type="application/rss+xml" title="Gophish - Blog" href="https://getgophish.com/blog/index.xml" />
</head>
<body>
<div id="layout" class="pure-g">
<div class="sidebar pure-u-1 pure-u-md-1-4">
<div class="header">
<hgroup>
<h1 class="brand-title"><a href="https://getgophish.com/blog">Gophish - Blog</a></h1>
<h2 class="brand-tagline"></h2>
</hgroup>
<nav class="nav">
<ul class="nav-list">
<li class="nav-item">
<a class="pure-button" href="http://getgophish.com"><i class="fa fa-home"></i> home</a>
</li>
<li class="nav-item">
<a class="pure-button" href="https://getgophish.com/blog/index.xml"><i class="fa fa-rss"></i> rss</a>
</li>
</ul>
</nav>
</div>
</div>
<div class="content pure-u-1 pure-u-md-3-4">
<div>
<div class="posts">
<h1 class="content-subhead">01 Feb 2016, 07:00</h1>
<section class="post">
<header class="post-header">
<a href="https://getgophish.com/blog/post/database-migrations-in-go/" class="post-title">Handling Database Migrations in Go</a>
<p class="post-meta">
</p>
</header>
<div class="post-description">
<h3 id="why-you-should-version-your-database:664f01dc60472cd080b34187311f6c6f">Why You Should Version Your Database</h3>
<blockquote>
<p>&ldquo;I got my database schema correct on the first try.&rdquo;</p>
<p>-No one ever.</p>
</blockquote>
<p>Like most big projects, gophish needed a way to automatically manage changes to our database schema. As new features were being added, we found ourselves in a situation that required us to add or modify columns and tables to store the new data.</p>
<p>In a hosted environment, this is no problem since we control the database and can make schema changes as we see fit. Gophish is different, in that it is software intentionally designed to run on the client&rsquo;s machine. This means that as we rollout updates to gophish&rsquo;s backend database, we need a way to easily update (or rollback!) changes to the database structure. A versioning system is a perfect fit, which introduces the idea of migrations.</p>
<h4 id="what-is-a-migration:664f01dc60472cd080b34187311f6c6f">What is a <em>Migration</em>?</h4>
<p>A migration is nothing more than a set of SQL commands to make changes to a database. Every migration typically has two parts: how to apply the changes you want, and how to roll them back.</p>
<p>To version control our database, we can create a folder holding multiple migration files. Each file will have an identifier so we know which migration should be applied and in which order. Then, we can store which version our database is currently at in the database itself so if we ever add migrations in the future, we can tell where we left off.</p>
<p>There are tools that can automate this process for us. We settled on a well-known database migration tool called <a href="https://bitbucket.org/liamstask/goose/"><code>goose</code></a>.</p>
<h3 id="introduction-to-goose:664f01dc60472cd080b34187311f6c6f">Introduction to <code>goose</code></h3>
<p>We chose to go with <a href="https://bitbucket.org/liamstask/goose/"><code>goose</code></a> since it seemed like a mature, fully-featured solution that would be easily integrated into our code. Goose typically works through the use of its command line tool aptly named <code>goose</code>.</p>
<p>To set things up, we first need to create the following folder structure:</p>
<pre><code>| db/
| | migrations/
| `-dbconf.yml
</code></pre>
<p>Our migrations will be stored in the <code>migrations</code> folder as a series of SQL files. Before we can create migrations, we have to specify the configuration for <code>goose</code> to use. This is found in the <code>dbconf.yml</code> file. In our case, we used the following configuration:</p>
<pre><code>production:
driver: sqlite3
open: gophish.db
dialect: sqlite3
import: github.com/mattn/go-sqlite3
</code></pre>
<p>This configuration specifies a single environment, <code>production</code>, that manages a SQLite database.</p>
<p>Now that we have created our configuration file, we can start making our migrations. Unfortunately, this is where the hurdles began.</p>
<h3 id="a-little-about-gophish:664f01dc60472cd080b34187311f6c6f">A Little About Gophish</h3>
<p>Normally, migrations are something that is considered early on in the database creation process. Unfortunately, our schema was already defined and we had clients already running gophish. So, we needed to orchestrate <code>goose</code> in such a way that we could create and apply our migrations without messing up any data that was already in the client&rsquo;s databases.</p>
<p>The first step was creating the migrations. To handle this, we first created an empty migration file using the following:</p>
<pre><code>goose -env production create 0.1.2_browser_post sql
goose: created ~\go\src\github.com\gophish\gophish\db\migrations\20160130184410_0.1.2_browser_post.sql
</code></pre>
<p>This command created a new empty SQL file in our migrations folder that looks like this:</p>
<pre><code>-- +goose Up
-- SQL in section 'Up' is executed when this migration is applied
-- +goose Down
-- SQL section 'Down' is executed when this migration is rolled back
</code></pre>
<p>For our first migration, we decided to baseline our schema to the current version. To do this, we simply exported our existing schema using the sqlite3 tool. That gave us all of our <code>CREATE TABLE</code> statements that setup our tables and default data. We then copy/pasted those statements below the <code>-- +goose Up</code> section of the migrations.</p>
<p>The one change we made was to add <code>IF NOT EXISTS</code> to all of our table creation statements. This meant that if the client already had a database setup, this migration would be applied, but no changes would be made - exactly what we want.</p>
<p>The final step to create this migration was to add the rollback statements. Since this was creating the database, <code>DROP TABLE</code> equivalent statements worked just fine. You can see our final migration file <a href="https://raw.githubusercontent.com/gophish/gophish/master/db/migrations/20160118194630_init.sql">here</a>.</p>
<p>Now for the next hurdle. Traditionally, migrations work by creating a new migration file and running <code>goose up</code>. Then, <code>goose</code> will compare your database version with the migration files it finds. If there are migrations that need to be applied, it will apply them in order until you are at the current version.</p>
<p>While the <code>goose up</code> command can work if we control the database, there&rsquo;s simply no way that we can expect our users to install <code>goose</code> and run <code>goose up</code> every time we want to make a database change. Our goal has always been to make the lives of our users easier, so this simply wouldn&rsquo;t work. This meant that we needed to handle the migrations in our code.</p>
<p>Fortunately for us, the <code>goose</code> CLI wraps a rich library that we can use. We were able to integrate this directly into our <code>Setup()</code> function to apply migrations automatically.</p>
<p>First, we created the <code>gooose.DBConf</code> struct to hold the configuration (a programmatic copy of our <code>dbconf.yml</code> file).</p>
<pre><code class="language-golang">// Setup the goose configuration
migrateConf := &amp;goose.DBConf{
MigrationsDir: config.Conf.MigrationsPath,
Env: &quot;production&quot;,
Driver: goose.DBDriver{
Name: &quot;sqlite3&quot;,
OpenStr: config.Conf.DBPath,
Import: &quot;github.com/mattn/go-sqlite3&quot;,
Dialect: &amp;goose.Sqlite3Dialect{},
},
}
</code></pre>
<p>Next, we need to figure out the latest database version supported by our migrations. This gives us the final &ldquo;goal&rdquo; migration that we want to upgrade to. We can do this via the function <a href="https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#GetMostRecentDBVersion"><code>goose.GetMostRecentDBVersion</code></a>.</p>
<pre><code class="language-golang">// Get the latest possible migration
latest, err := goose.GetMostRecentDBVersion(migrateConf.MigrationsDir)
if err != nil {
Logger.Println(err)
return err
}
</code></pre>
<p>And finally, we need to apply our migrations. <code>Goose</code> has a function called <a href="https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#RunMigrationsOnDb"><code>goose.RunMigrationsOnDb</code></a> which expects an existing <a href="https://golang.org/pkg/database/sql/#DB"><code>sql.DB</code></a> object. Since gophish uses the ORM <a href="https://github.com/jinzhu/gorm"><code>gorm</code></a>, we already had a <code>sql.DB</code> object already initialized that we could use to send to <code>goose</code>. This was stored in the <code>db</code> variable.</p>
<pre><code class="language-golang">// Migrate up to the latest version
err = goose.RunMigrationsOnDb(migrateConf, migrateConf.MigrationsDir, latest, db.DB())
if err != nil {
Logger.Println(err)
return err
}
</code></pre>
<p>That&rsquo;s it! You can find our full <code>Setup()</code> function <a href="https://github.com/gophish/gophish/blob/master/models/models.go#L61">here.</a> To handle any additional migrations, all we need to do is run <code>goose create</code> again, add the SQL that makes up the migration, and push out the new file. The next time clients update gophish and restart the executable, the database migrations will be applied automatically!</p>
<p>If this kind of stuff is interesting to you, and you want to see a full example of a web app written in Go, check out gophish by clicking below.</p>
<a href="https://github.com/gophish/gophish" class="btn">Download gophish</a>
</div>
</section>
</div>
<div class="footer">
<div class="pure-menu pure-menu-horizontal pure-menu-open">
<ul>
<li>Powered by <a class="hugo" href="http://hugo.spf13.com/" target="_blank">hugo</a></li>
</ul>
</div>
</div>
<script src="https://getgophish.com/blog/js/all.min.js"></script>
</div>
</div>
</div>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-47018345-1', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>

141
blog/tags/go/index.xml Normal file
View File

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Go on Gophish - Blog</title>
<link>https://getgophish.com/blog/tags/go/</link>
<description>Recent content in Go on Gophish - Blog</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<lastBuildDate>Mon, 01 Feb 2016 07:00:00 -0600</lastBuildDate>
<atom:link href="https://getgophish.com/blog/tags/go/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>Handling Database Migrations in Go</title>
<link>https://getgophish.com/blog/post/database-migrations-in-go/</link>
<pubDate>Mon, 01 Feb 2016 07:00:00 -0600</pubDate>
<guid>https://getgophish.com/blog/post/database-migrations-in-go/</guid>
<description>
&lt;h3 id=&#34;why-you-should-version-your-database:664f01dc60472cd080b34187311f6c6f&#34;&gt;Why You Should Version Your Database&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;I got my database schema correct on the first try.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;-No one ever.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Like most big projects, gophish needed a way to automatically manage changes to our database schema. As new features were being added, we found ourselves in a situation that required us to add or modify columns and tables to store the new data.&lt;/p&gt;
&lt;p&gt;In a hosted environment, this is no problem since we control the database and can make schema changes as we see fit. Gophish is different, in that it is software intentionally designed to run on the client&amp;rsquo;s machine. This means that as we rollout updates to gophish&amp;rsquo;s backend database, we need a way to easily update (or rollback!) changes to the database structure. A versioning system is a perfect fit, which introduces the idea of migrations.&lt;/p&gt;
&lt;h4 id=&#34;what-is-a-migration:664f01dc60472cd080b34187311f6c6f&#34;&gt;What is a &lt;em&gt;Migration&lt;/em&gt;?&lt;/h4&gt;
&lt;p&gt;A migration is nothing more than a set of SQL commands to make changes to a database. Every migration typically has two parts: how to apply the changes you want, and how to roll them back.&lt;/p&gt;
&lt;p&gt;To version control our database, we can create a folder holding multiple migration files. Each file will have an identifier so we know which migration should be applied and in which order. Then, we can store which version our database is currently at in the database itself so if we ever add migrations in the future, we can tell where we left off.&lt;/p&gt;
&lt;p&gt;There are tools that can automate this process for us. We settled on a well-known database migration tool called &lt;a href=&#34;https://bitbucket.org/liamstask/goose/&#34;&gt;&lt;code&gt;goose&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;introduction-to-goose:664f01dc60472cd080b34187311f6c6f&#34;&gt;Introduction to &lt;code&gt;goose&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;We chose to go with &lt;a href=&#34;https://bitbucket.org/liamstask/goose/&#34;&gt;&lt;code&gt;goose&lt;/code&gt;&lt;/a&gt; since it seemed like a mature, fully-featured solution that would be easily integrated into our code. Goose typically works through the use of its command line tool aptly named &lt;code&gt;goose&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To set things up, we first need to create the following folder structure:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;| db/
| | migrations/
| `-dbconf.yml
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our migrations will be stored in the &lt;code&gt;migrations&lt;/code&gt; folder as a series of SQL files. Before we can create migrations, we have to specify the configuration for &lt;code&gt;goose&lt;/code&gt; to use. This is found in the &lt;code&gt;dbconf.yml&lt;/code&gt; file. In our case, we used the following configuration:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;production:
driver: sqlite3
open: gophish.db
dialect: sqlite3
import: github.com/mattn/go-sqlite3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This configuration specifies a single environment, &lt;code&gt;production&lt;/code&gt;, that manages a SQLite database.&lt;/p&gt;
&lt;p&gt;Now that we have created our configuration file, we can start making our migrations. Unfortunately, this is where the hurdles began.&lt;/p&gt;
&lt;h3 id=&#34;a-little-about-gophish:664f01dc60472cd080b34187311f6c6f&#34;&gt;A Little About Gophish&lt;/h3&gt;
&lt;p&gt;Normally, migrations are something that is considered early on in the database creation process. Unfortunately, our schema was already defined and we had clients already running gophish. So, we needed to orchestrate &lt;code&gt;goose&lt;/code&gt; in such a way that we could create and apply our migrations without messing up any data that was already in the client&amp;rsquo;s databases.&lt;/p&gt;
&lt;p&gt;The first step was creating the migrations. To handle this, we first created an empty migration file using the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;goose -env production create 0.1.2_browser_post sql
goose: created ~\go\src\github.com\gophish\gophish\db\migrations\20160130184410_0.1.2_browser_post.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command created a new empty SQL file in our migrations folder that looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-- +goose Up
-- SQL in section &#39;Up&#39; is executed when this migration is applied
-- +goose Down
-- SQL section &#39;Down&#39; is executed when this migration is rolled back
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For our first migration, we decided to baseline our schema to the current version. To do this, we simply exported our existing schema using the sqlite3 tool. That gave us all of our &lt;code&gt;CREATE TABLE&lt;/code&gt; statements that setup our tables and default data. We then copy/pasted those statements below the &lt;code&gt;-- +goose Up&lt;/code&gt; section of the migrations.&lt;/p&gt;
&lt;p&gt;The one change we made was to add &lt;code&gt;IF NOT EXISTS&lt;/code&gt; to all of our table creation statements. This meant that if the client already had a database setup, this migration would be applied, but no changes would be made - exactly what we want.&lt;/p&gt;
&lt;p&gt;The final step to create this migration was to add the rollback statements. Since this was creating the database, &lt;code&gt;DROP TABLE&lt;/code&gt; equivalent statements worked just fine. You can see our final migration file &lt;a href=&#34;https://raw.githubusercontent.com/gophish/gophish/master/db/migrations/20160118194630_init.sql&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now for the next hurdle. Traditionally, migrations work by creating a new migration file and running &lt;code&gt;goose up&lt;/code&gt;. Then, &lt;code&gt;goose&lt;/code&gt; will compare your database version with the migration files it finds. If there are migrations that need to be applied, it will apply them in order until you are at the current version.&lt;/p&gt;
&lt;p&gt;While the &lt;code&gt;goose up&lt;/code&gt; command can work if we control the database, there&amp;rsquo;s simply no way that we can expect our users to install &lt;code&gt;goose&lt;/code&gt; and run &lt;code&gt;goose up&lt;/code&gt; every time we want to make a database change. Our goal has always been to make the lives of our users easier, so this simply wouldn&amp;rsquo;t work. This meant that we needed to handle the migrations in our code.&lt;/p&gt;
&lt;p&gt;Fortunately for us, the &lt;code&gt;goose&lt;/code&gt; CLI wraps a rich library that we can use. We were able to integrate this directly into our &lt;code&gt;Setup()&lt;/code&gt; function to apply migrations automatically.&lt;/p&gt;
&lt;p&gt;First, we created the &lt;code&gt;gooose.DBConf&lt;/code&gt; struct to hold the configuration (a programmatic copy of our &lt;code&gt;dbconf.yml&lt;/code&gt; file).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;// Setup the goose configuration
migrateConf := &amp;amp;goose.DBConf{
MigrationsDir: config.Conf.MigrationsPath,
Env: &amp;quot;production&amp;quot;,
Driver: goose.DBDriver{
Name: &amp;quot;sqlite3&amp;quot;,
OpenStr: config.Conf.DBPath,
Import: &amp;quot;github.com/mattn/go-sqlite3&amp;quot;,
Dialect: &amp;amp;goose.Sqlite3Dialect{},
},
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, we need to figure out the latest database version supported by our migrations. This gives us the final &amp;ldquo;goal&amp;rdquo; migration that we want to upgrade to. We can do this via the function &lt;a href=&#34;https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#GetMostRecentDBVersion&#34;&gt;&lt;code&gt;goose.GetMostRecentDBVersion&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;// Get the latest possible migration
latest, err := goose.GetMostRecentDBVersion(migrateConf.MigrationsDir)
if err != nil {
Logger.Println(err)
return err
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally, we need to apply our migrations. &lt;code&gt;Goose&lt;/code&gt; has a function called &lt;a href=&#34;https://godoc.org/bitbucket.org/liamstask/goose/lib/goose#RunMigrationsOnDb&#34;&gt;&lt;code&gt;goose.RunMigrationsOnDb&lt;/code&gt;&lt;/a&gt; which expects an existing &lt;a href=&#34;https://golang.org/pkg/database/sql/#DB&#34;&gt;&lt;code&gt;sql.DB&lt;/code&gt;&lt;/a&gt; object. Since gophish uses the ORM &lt;a href=&#34;https://github.com/jinzhu/gorm&#34;&gt;&lt;code&gt;gorm&lt;/code&gt;&lt;/a&gt;, we already had a &lt;code&gt;sql.DB&lt;/code&gt; object already initialized that we could use to send to &lt;code&gt;goose&lt;/code&gt;. This was stored in the &lt;code&gt;db&lt;/code&gt; variable.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-golang&#34;&gt;// Migrate up to the latest version
err = goose.RunMigrationsOnDb(migrateConf, migrateConf.MigrationsDir, latest, db.DB())
if err != nil {
Logger.Println(err)
return err
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;rsquo;s it! You can find our full &lt;code&gt;Setup()&lt;/code&gt; function &lt;a href=&#34;https://github.com/gophish/gophish/blob/master/models/models.go#L61&#34;&gt;here.&lt;/a&gt; To handle any additional migrations, all we need to do is run &lt;code&gt;goose create&lt;/code&gt; again, add the SQL that makes up the migration, and push out the new file. The next time clients update gophish and restart the executable, the database migrations will be applied automatically!&lt;/p&gt;
&lt;p&gt;If this kind of stuff is interesting to you, and you want to see a full example of a web app written in Go, check out gophish by clicking below.&lt;/p&gt;
&lt;a href=&#34;https://github.com/gophish/gophish&#34; class=&#34;btn&#34;&gt;Download gophish&lt;/a&gt;
</description>
</item>
</channel>
</rss>

View File

@ -0,0 +1 @@
<!DOCTYPE html><html><head><link rel="canonical" href="https://getgophish.com/blog/tags/go/"/><meta http-equiv="content-type" content="text/html; charset=utf-8" /><meta http-equiv="refresh" content="0;url=https://getgophish.com/blog/tags/go/" /></head></html>

View File

@ -63,6 +63,117 @@
<div class="posts">
<h1 class="content-subhead">01 Feb 2016, 06:00</h1>
<section class="post">
<header class="post-header">
<a href="https://getgophish.com/blog/post/release-0.1.1/" class="post-title">Announcing gophish v0.1.1</a>
<p class="post-meta">
</p>
</header>
<div class="post-description">
<img src="/blog/images/gophish_purple.png" alt="" class="pure-img" >
<p><em>Tl;dr - Download the release <a href="https://github.com/gophish/gophish/releases">here</a></em></p>
<h3 id="the-wait-is-over:1cea0120cd31cba0f7863bc47631176f"><strong>The wait is over!</strong></h3>
<p>The gophish team is excited to announce our first public beta version of gophish - version 0.1.1! This blog post will be a short introduction into what gophish is, as well as some of the insanely awesome features we&rsquo;ve created.</p>
<h3 id="what-is-gophish:1cea0120cd31cba0f7863bc47631176f">What is Gophish?</h3>
<p>Gophish is a phishing framework that makes the simulation of real-world phishing attacks dead-simple. The idea behind gophish is simple make industry-grade phishing training available to <em>everyone</em>.</p>
<p>&ldquo;Available&rdquo; in this case means two things </p>
<ul>
<li><strong>Affordable</strong> Gophish is currently open-source software that is completely free for anyone to use.</li>
<li><strong>Accessible</strong> Gophish is written in the Go programming language. This has the benefit that gophish releases are compiled binaries with no dependencies. In a nutshell, this makes installation as simple as “download and run”!</li>
</ul>
<h3 id="time-for-features:1cea0120cd31cba0f7863bc47631176f">Time For Features</h3>
<p>Ok, ok, enough with the intro. The idea of a phishing simulation platform isn&rsquo;t new. Let&rsquo;s take a look at some of the features that really set gophish apart and make it awesome.</p>
<h4 id="hosted-on-prem:1cea0120cd31cba0f7863bc47631176f">Hosted On-Prem</h4>
<p>There are many commercial offerings that provide phishing simulation/training. Unfortunately, these are SaaS solutions that require you to hand over your data to someone else.</p>
<p>Gophish is different in that it is meant to be hosted in-house. This keeps you data where it belongs - with you.</p>
<h4 id="download-run:1cea0120cd31cba0f7863bc47631176f">Download -&gt; Run</h4>
<p>For the few existing in-house solutions that exist, setup can be a <em>huge pain</em> (looking at you, Ruby gems). Your time is too valuable to be spent wrestling with dependencies trying to create the perfect setup that somehow magically allows the program to run.</p>
<p>Gophish was written in the Go programming language for this exact reason. To install gophish, all you have to do is download the zip file, extract the contents, and run the binary.</p>
<p>By doing this, you just started two webservers, populated a database, and setup a background worker to handle sending the mails. Now, your time can be spent making campaigns. Easy peasy.</p>
<h4 id="api-s-for-everything:1cea0120cd31cba0f7863bc47631176f">API&rsquo;s for <em>Everything</em>.</h4>
<p>Gophish was built with automation first. This means that you can create scripts and clients that automate all the hard work for you. In addition to this, we keep up-to-date <a href="/documentation/api/">API docs</a> that describe each API endpoint in detail.</p>
<h4 id="rock-solid-documentation:1cea0120cd31cba0f7863bc47631176f">Rock-Solid Documentation</h4>
<p>Speaking of API docs, we take documentation very seriously. We take documentation seriously because we take our user experience seriously. If you can&rsquo;t find what you need to use and troubleshoot gophish, we&rsquo;ve failed. Just take a look at our comprehensive <a href="/documentation/Gophish%20User%20Guide.pdf">user guide</a>, <a href="/documentation/api/">API documentation</a>, and even <a href="http://godoc.org/github.com/gophish/gophish">fully documented code</a>.</p>
<p>If you ever find something missing in our documentation, <a href="/support">we want to know!</a></p>
<h4 id="beautiful-ui:1cea0120cd31cba0f7863bc47631176f">Beautiful UI</h4>
<p>While the API is the core of gophish&rsquo;s functionality, we also provide a gorgeous admin UI. This UI is simply a wrapper on top of the underlying API. Nothing says more than screenshots:</p>
<p><figure>
<img src="/blog/images/screenshots/login.png" alt="" class="blog-image" >
<figcap>Login Screen</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/new_group.png" alt="" class="blog-image" >
<figcap>Creating a New Group</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/new_template.png" alt="" class="blog-image" >
<figcap>Creating an Email Template</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/import_site.png" alt="" class="blog-image" >
<figcap>Importing a Site</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/campaign_results.png" alt="" class="blog-image" >
<figcap>Viewing Campaign Results</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/timeline.png" alt="" class="blog-image" >
<figcap>Viewing the Timeline for a Target</figcap>
</figure>
</p>
<h3 id="take-gophish-for-a-spin:1cea0120cd31cba0f7863bc47631176f">Take Gophish for a Spin!</h3>
<p>These features only scratch the surface when it comes to what makes gophish great, and we aren&rsquo;t anywhere near done yet. To explore these features for yourself, take gophish for a spin!</p>
<p>We hope you enjoy gophish and are excited for all the new features that will be released soon! In the meantime, if you ever have any questions, comments, or issues, <a href="/support">we want to hear from you</a>!</p>
<p>-The Gophish Team</p>
<p><a href="https://github.com/gophish/gophish/releases" class="btn">Download gophish</a>
</p>
</div>
</section>
<h1 class="content-subhead">07 Jan 2016, 22:05</h1>
<section class="post">
<header class="post-header">

View File

@ -6,9 +6,112 @@
<description>Recent content in Gophish on Gophish - Blog</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<lastBuildDate>Thu, 07 Jan 2016 22:05:58 -0600</lastBuildDate>
<lastBuildDate>Mon, 01 Feb 2016 06:00:00 -0600</lastBuildDate>
<atom:link href="https://getgophish.com/blog/tags/gophish/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>Announcing gophish v0.1.1</title>
<link>https://getgophish.com/blog/post/release-0.1.1/</link>
<pubDate>Mon, 01 Feb 2016 06:00:00 -0600</pubDate>
<guid>https://getgophish.com/blog/post/release-0.1.1/</guid>
<description>
&lt;img src=&#34;https://getgophish.com/blog/blog/images/gophish_purple.png&#34; alt=&#34;&#34; class=&#34;pure-img&#34; &gt;
&lt;p&gt;&lt;em&gt;Tl;dr - Download the release &lt;a href=&#34;https://github.com/gophish/gophish/releases&#34;&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;the-wait-is-over:1cea0120cd31cba0f7863bc47631176f&#34;&gt;&lt;strong&gt;The wait is over!&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The gophish team is excited to announce our first public beta version of gophish - version 0.1.1! This blog post will be a short introduction into what gophish is, as well as some of the insanely awesome features we&amp;rsquo;ve created.&lt;/p&gt;
&lt;h3 id=&#34;what-is-gophish:1cea0120cd31cba0f7863bc47631176f&#34;&gt;What is Gophish?&lt;/h3&gt;
&lt;p&gt;Gophish is a phishing framework that makes the simulation of real-world phishing attacks dead-simple. The idea behind gophish is simple make industry-grade phishing training available to &lt;em&gt;everyone&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Available&amp;rdquo; in this case means two things &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Affordable&lt;/strong&gt; Gophish is currently open-source software that is completely free for anyone to use.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accessible&lt;/strong&gt; Gophish is written in the Go programming language. This has the benefit that gophish releases are compiled binaries with no dependencies. In a nutshell, this makes installation as simple as “download and run”!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;time-for-features:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Time For Features&lt;/h3&gt;
&lt;p&gt;Ok, ok, enough with the intro. The idea of a phishing simulation platform isn&amp;rsquo;t new. Let&amp;rsquo;s take a look at some of the features that really set gophish apart and make it awesome.&lt;/p&gt;
&lt;h4 id=&#34;hosted-on-prem:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Hosted On-Prem&lt;/h4&gt;
&lt;p&gt;There are many commercial offerings that provide phishing simulation/training. Unfortunately, these are SaaS solutions that require you to hand over your data to someone else.&lt;/p&gt;
&lt;p&gt;Gophish is different in that it is meant to be hosted in-house. This keeps you data where it belongs - with you.&lt;/p&gt;
&lt;h4 id=&#34;download-run:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Download -&amp;gt; Run&lt;/h4&gt;
&lt;p&gt;For the few existing in-house solutions that exist, setup can be a &lt;em&gt;huge pain&lt;/em&gt; (looking at you, Ruby gems). Your time is too valuable to be spent wrestling with dependencies trying to create the perfect setup that somehow magically allows the program to run.&lt;/p&gt;
&lt;p&gt;Gophish was written in the Go programming language for this exact reason. To install gophish, all you have to do is download the zip file, extract the contents, and run the binary.&lt;/p&gt;
&lt;p&gt;By doing this, you just started two webservers, populated a database, and setup a background worker to handle sending the mails. Now, your time can be spent making campaigns. Easy peasy.&lt;/p&gt;
&lt;h4 id=&#34;api-s-for-everything:1cea0120cd31cba0f7863bc47631176f&#34;&gt;API&amp;rsquo;s for &lt;em&gt;Everything&lt;/em&gt;.&lt;/h4&gt;
&lt;p&gt;Gophish was built with automation first. This means that you can create scripts and clients that automate all the hard work for you. In addition to this, we keep up-to-date &lt;a href=&#34;https://getgophish.com/blog/documentation/api/&#34;&gt;API docs&lt;/a&gt; that describe each API endpoint in detail.&lt;/p&gt;
&lt;h4 id=&#34;rock-solid-documentation:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Rock-Solid Documentation&lt;/h4&gt;
&lt;p&gt;Speaking of API docs, we take documentation very seriously. We take documentation seriously because we take our user experience seriously. If you can&amp;rsquo;t find what you need to use and troubleshoot gophish, we&amp;rsquo;ve failed. Just take a look at our comprehensive &lt;a href=&#34;https://getgophish.com/blog/documentation/Gophish%20User%20Guide.pdf&#34;&gt;user guide&lt;/a&gt;, &lt;a href=&#34;https://getgophish.com/blog/documentation/api/&#34;&gt;API documentation&lt;/a&gt;, and even &lt;a href=&#34;http://godoc.org/github.com/gophish/gophish&#34;&gt;fully documented code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you ever find something missing in our documentation, &lt;a href=&#34;https://getgophish.com/blog/support&#34;&gt;we want to know!&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&#34;beautiful-ui:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Beautiful UI&lt;/h4&gt;
&lt;p&gt;While the API is the core of gophish&amp;rsquo;s functionality, we also provide a gorgeous admin UI. This UI is simply a wrapper on top of the underlying API. Nothing says more than screenshots:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/login.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Login Screen&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/new_group.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Creating a New Group&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/new_template.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Creating an Email Template&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/import_site.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Importing a Site&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/campaign_results.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Viewing Campaign Results&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/timeline.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Viewing the Timeline for a Target&lt;/figcap&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id=&#34;take-gophish-for-a-spin:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Take Gophish for a Spin!&lt;/h3&gt;
&lt;p&gt;These features only scratch the surface when it comes to what makes gophish great, and we aren&amp;rsquo;t anywhere near done yet. To explore these features for yourself, take gophish for a spin!&lt;/p&gt;
&lt;p&gt;We hope you enjoy gophish and are excited for all the new features that will be released soon! In the meantime, if you ever have any questions, comments, or issues, &lt;a href=&#34;https://getgophish.com/blog/support&#34;&gt;we want to hear from you&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;-The Gophish Team&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/gophish/gophish/releases&#34; class=&#34;btn&#34;&gt;Download gophish&lt;/a&gt;
&lt;/p&gt;
</description>
</item>
<item>
<title>Introducing gophish</title>
<link>https://getgophish.com/blog/post/hello-world/</link>

View File

@ -0,0 +1,204 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Release &middot; Gophish - Blog</title>
<meta name="description" content="">
<meta name="generator" content="Hugo 0.15" />
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Release &middot; Gophish - Blog">
<meta name="twitter:description" content="">
<meta property="og:type" content="article">
<meta property="og:title" content="Release &middot; Gophish - Blog">
<meta property="og:description" content="">
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700|Oxygen:400,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/pure-min.css">
<!--[if lte IE 8]>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/grids-responsive-old-ie-min.css">
<![endif]-->
<!--[if gt IE 8]><!-->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/0.6.0/grids-responsive-min.css">
<!--<![endif]-->
<link rel="stylesheet" href="https://getgophish.com/blog/css/all.min.css">
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="alternate" type="application/rss+xml" title="Gophish - Blog" href="https://getgophish.com/blog/index.xml" />
</head>
<body>
<div id="layout" class="pure-g">
<div class="sidebar pure-u-1 pure-u-md-1-4">
<div class="header">
<hgroup>
<h1 class="brand-title"><a href="https://getgophish.com/blog">Gophish - Blog</a></h1>
<h2 class="brand-tagline"></h2>
</hgroup>
<nav class="nav">
<ul class="nav-list">
<li class="nav-item">
<a class="pure-button" href="http://getgophish.com"><i class="fa fa-home"></i> home</a>
</li>
<li class="nav-item">
<a class="pure-button" href="https://getgophish.com/blog/index.xml"><i class="fa fa-rss"></i> rss</a>
</li>
</ul>
</nav>
</div>
</div>
<div class="content pure-u-1 pure-u-md-3-4">
<div>
<div class="posts">
<h1 class="content-subhead">01 Feb 2016, 06:00</h1>
<section class="post">
<header class="post-header">
<a href="https://getgophish.com/blog/post/release-0.1.1/" class="post-title">Announcing gophish v0.1.1</a>
<p class="post-meta">
</p>
</header>
<div class="post-description">
<img src="/blog/images/gophish_purple.png" alt="" class="pure-img" >
<p><em>Tl;dr - Download the release <a href="https://github.com/gophish/gophish/releases">here</a></em></p>
<h3 id="the-wait-is-over:1cea0120cd31cba0f7863bc47631176f"><strong>The wait is over!</strong></h3>
<p>The gophish team is excited to announce our first public beta version of gophish - version 0.1.1! This blog post will be a short introduction into what gophish is, as well as some of the insanely awesome features we&rsquo;ve created.</p>
<h3 id="what-is-gophish:1cea0120cd31cba0f7863bc47631176f">What is Gophish?</h3>
<p>Gophish is a phishing framework that makes the simulation of real-world phishing attacks dead-simple. The idea behind gophish is simple make industry-grade phishing training available to <em>everyone</em>.</p>
<p>&ldquo;Available&rdquo; in this case means two things </p>
<ul>
<li><strong>Affordable</strong> Gophish is currently open-source software that is completely free for anyone to use.</li>
<li><strong>Accessible</strong> Gophish is written in the Go programming language. This has the benefit that gophish releases are compiled binaries with no dependencies. In a nutshell, this makes installation as simple as “download and run”!</li>
</ul>
<h3 id="time-for-features:1cea0120cd31cba0f7863bc47631176f">Time For Features</h3>
<p>Ok, ok, enough with the intro. The idea of a phishing simulation platform isn&rsquo;t new. Let&rsquo;s take a look at some of the features that really set gophish apart and make it awesome.</p>
<h4 id="hosted-on-prem:1cea0120cd31cba0f7863bc47631176f">Hosted On-Prem</h4>
<p>There are many commercial offerings that provide phishing simulation/training. Unfortunately, these are SaaS solutions that require you to hand over your data to someone else.</p>
<p>Gophish is different in that it is meant to be hosted in-house. This keeps you data where it belongs - with you.</p>
<h4 id="download-run:1cea0120cd31cba0f7863bc47631176f">Download -&gt; Run</h4>
<p>For the few existing in-house solutions that exist, setup can be a <em>huge pain</em> (looking at you, Ruby gems). Your time is too valuable to be spent wrestling with dependencies trying to create the perfect setup that somehow magically allows the program to run.</p>
<p>Gophish was written in the Go programming language for this exact reason. To install gophish, all you have to do is download the zip file, extract the contents, and run the binary.</p>
<p>By doing this, you just started two webservers, populated a database, and setup a background worker to handle sending the mails. Now, your time can be spent making campaigns. Easy peasy.</p>
<h4 id="api-s-for-everything:1cea0120cd31cba0f7863bc47631176f">API&rsquo;s for <em>Everything</em>.</h4>
<p>Gophish was built with automation first. This means that you can create scripts and clients that automate all the hard work for you. In addition to this, we keep up-to-date <a href="/documentation/api/">API docs</a> that describe each API endpoint in detail.</p>
<h4 id="rock-solid-documentation:1cea0120cd31cba0f7863bc47631176f">Rock-Solid Documentation</h4>
<p>Speaking of API docs, we take documentation very seriously. We take documentation seriously because we take our user experience seriously. If you can&rsquo;t find what you need to use and troubleshoot gophish, we&rsquo;ve failed. Just take a look at our comprehensive <a href="/documentation/Gophish%20User%20Guide.pdf">user guide</a>, <a href="/documentation/api/">API documentation</a>, and even <a href="http://godoc.org/github.com/gophish/gophish">fully documented code</a>.</p>
<p>If you ever find something missing in our documentation, <a href="/support">we want to know!</a></p>
<h4 id="beautiful-ui:1cea0120cd31cba0f7863bc47631176f">Beautiful UI</h4>
<p>While the API is the core of gophish&rsquo;s functionality, we also provide a gorgeous admin UI. This UI is simply a wrapper on top of the underlying API. Nothing says more than screenshots:</p>
<p><figure>
<img src="/blog/images/screenshots/login.png" alt="" class="blog-image" >
<figcap>Login Screen</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/new_group.png" alt="" class="blog-image" >
<figcap>Creating a New Group</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/new_template.png" alt="" class="blog-image" >
<figcap>Creating an Email Template</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/import_site.png" alt="" class="blog-image" >
<figcap>Importing a Site</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/campaign_results.png" alt="" class="blog-image" >
<figcap>Viewing Campaign Results</figcap>
</figure>
<figure>
<img src="/blog/images/screenshots/timeline.png" alt="" class="blog-image" >
<figcap>Viewing the Timeline for a Target</figcap>
</figure>
</p>
<h3 id="take-gophish-for-a-spin:1cea0120cd31cba0f7863bc47631176f">Take Gophish for a Spin!</h3>
<p>These features only scratch the surface when it comes to what makes gophish great, and we aren&rsquo;t anywhere near done yet. To explore these features for yourself, take gophish for a spin!</p>
<p>We hope you enjoy gophish and are excited for all the new features that will be released soon! In the meantime, if you ever have any questions, comments, or issues, <a href="/support">we want to hear from you</a>!</p>
<p>-The Gophish Team</p>
<p><a href="https://github.com/gophish/gophish/releases" class="btn">Download gophish</a>
</p>
</div>
</section>
</div>
<div class="footer">
<div class="pure-menu pure-menu-horizontal pure-menu-open">
<ul>
<li>Powered by <a class="hugo" href="http://hugo.spf13.com/" target="_blank">hugo</a></li>
</ul>
</div>
</div>
<script src="https://getgophish.com/blog/js/all.min.js"></script>
</div>
</div>
</div>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-47018345-1', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>

116
blog/tags/release/index.xml Normal file
View File

@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Release on Gophish - Blog</title>
<link>https://getgophish.com/blog/tags/release/</link>
<description>Recent content in Release on Gophish - Blog</description>
<generator>Hugo -- gohugo.io</generator>
<language>en-us</language>
<lastBuildDate>Mon, 01 Feb 2016 06:00:00 -0600</lastBuildDate>
<atom:link href="https://getgophish.com/blog/tags/release/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>Announcing gophish v0.1.1</title>
<link>https://getgophish.com/blog/post/release-0.1.1/</link>
<pubDate>Mon, 01 Feb 2016 06:00:00 -0600</pubDate>
<guid>https://getgophish.com/blog/post/release-0.1.1/</guid>
<description>
&lt;img src=&#34;https://getgophish.com/blog/blog/images/gophish_purple.png&#34; alt=&#34;&#34; class=&#34;pure-img&#34; &gt;
&lt;p&gt;&lt;em&gt;Tl;dr - Download the release &lt;a href=&#34;https://github.com/gophish/gophish/releases&#34;&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;the-wait-is-over:1cea0120cd31cba0f7863bc47631176f&#34;&gt;&lt;strong&gt;The wait is over!&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The gophish team is excited to announce our first public beta version of gophish - version 0.1.1! This blog post will be a short introduction into what gophish is, as well as some of the insanely awesome features we&amp;rsquo;ve created.&lt;/p&gt;
&lt;h3 id=&#34;what-is-gophish:1cea0120cd31cba0f7863bc47631176f&#34;&gt;What is Gophish?&lt;/h3&gt;
&lt;p&gt;Gophish is a phishing framework that makes the simulation of real-world phishing attacks dead-simple. The idea behind gophish is simple make industry-grade phishing training available to &lt;em&gt;everyone&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Available&amp;rdquo; in this case means two things &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Affordable&lt;/strong&gt; Gophish is currently open-source software that is completely free for anyone to use.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accessible&lt;/strong&gt; Gophish is written in the Go programming language. This has the benefit that gophish releases are compiled binaries with no dependencies. In a nutshell, this makes installation as simple as “download and run”!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;time-for-features:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Time For Features&lt;/h3&gt;
&lt;p&gt;Ok, ok, enough with the intro. The idea of a phishing simulation platform isn&amp;rsquo;t new. Let&amp;rsquo;s take a look at some of the features that really set gophish apart and make it awesome.&lt;/p&gt;
&lt;h4 id=&#34;hosted-on-prem:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Hosted On-Prem&lt;/h4&gt;
&lt;p&gt;There are many commercial offerings that provide phishing simulation/training. Unfortunately, these are SaaS solutions that require you to hand over your data to someone else.&lt;/p&gt;
&lt;p&gt;Gophish is different in that it is meant to be hosted in-house. This keeps you data where it belongs - with you.&lt;/p&gt;
&lt;h4 id=&#34;download-run:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Download -&amp;gt; Run&lt;/h4&gt;
&lt;p&gt;For the few existing in-house solutions that exist, setup can be a &lt;em&gt;huge pain&lt;/em&gt; (looking at you, Ruby gems). Your time is too valuable to be spent wrestling with dependencies trying to create the perfect setup that somehow magically allows the program to run.&lt;/p&gt;
&lt;p&gt;Gophish was written in the Go programming language for this exact reason. To install gophish, all you have to do is download the zip file, extract the contents, and run the binary.&lt;/p&gt;
&lt;p&gt;By doing this, you just started two webservers, populated a database, and setup a background worker to handle sending the mails. Now, your time can be spent making campaigns. Easy peasy.&lt;/p&gt;
&lt;h4 id=&#34;api-s-for-everything:1cea0120cd31cba0f7863bc47631176f&#34;&gt;API&amp;rsquo;s for &lt;em&gt;Everything&lt;/em&gt;.&lt;/h4&gt;
&lt;p&gt;Gophish was built with automation first. This means that you can create scripts and clients that automate all the hard work for you. In addition to this, we keep up-to-date &lt;a href=&#34;https://getgophish.com/blog/documentation/api/&#34;&gt;API docs&lt;/a&gt; that describe each API endpoint in detail.&lt;/p&gt;
&lt;h4 id=&#34;rock-solid-documentation:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Rock-Solid Documentation&lt;/h4&gt;
&lt;p&gt;Speaking of API docs, we take documentation very seriously. We take documentation seriously because we take our user experience seriously. If you can&amp;rsquo;t find what you need to use and troubleshoot gophish, we&amp;rsquo;ve failed. Just take a look at our comprehensive &lt;a href=&#34;https://getgophish.com/blog/documentation/Gophish%20User%20Guide.pdf&#34;&gt;user guide&lt;/a&gt;, &lt;a href=&#34;https://getgophish.com/blog/documentation/api/&#34;&gt;API documentation&lt;/a&gt;, and even &lt;a href=&#34;http://godoc.org/github.com/gophish/gophish&#34;&gt;fully documented code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you ever find something missing in our documentation, &lt;a href=&#34;https://getgophish.com/blog/support&#34;&gt;we want to know!&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&#34;beautiful-ui:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Beautiful UI&lt;/h4&gt;
&lt;p&gt;While the API is the core of gophish&amp;rsquo;s functionality, we also provide a gorgeous admin UI. This UI is simply a wrapper on top of the underlying API. Nothing says more than screenshots:&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/login.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Login Screen&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/new_group.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Creating a New Group&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/new_template.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Creating an Email Template&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/import_site.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Importing a Site&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/campaign_results.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Viewing Campaign Results&lt;/figcap&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img src=&#34;https://getgophish.com/blog/blog/images/screenshots/timeline.png&#34; alt=&#34;&#34; class=&#34;blog-image&#34; &gt;
&lt;figcap&gt;Viewing the Timeline for a Target&lt;/figcap&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id=&#34;take-gophish-for-a-spin:1cea0120cd31cba0f7863bc47631176f&#34;&gt;Take Gophish for a Spin!&lt;/h3&gt;
&lt;p&gt;These features only scratch the surface when it comes to what makes gophish great, and we aren&amp;rsquo;t anywhere near done yet. To explore these features for yourself, take gophish for a spin!&lt;/p&gt;
&lt;p&gt;We hope you enjoy gophish and are excited for all the new features that will be released soon! In the meantime, if you ever have any questions, comments, or issues, &lt;a href=&#34;https://getgophish.com/blog/support&#34;&gt;we want to hear from you&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;-The Gophish Team&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/gophish/gophish/releases&#34; class=&#34;btn&#34;&gt;Download gophish&lt;/a&gt;
&lt;/p&gt;
</description>
</item>
</channel>
</rss>

View File

@ -0,0 +1 @@
<!DOCTYPE html><html><head><link rel="canonical" href="https://getgophish.com/blog/tags/release/"/><meta http-equiv="content-type" content="text/html; charset=utf-8" /><meta http-equiv="refresh" content="0;url=https://getgophish.com/blog/tags/release/" /></head></html>